设计模式之美学习-设计原则之单一职责(四)
什么是单一职责
一种理解是:把模块看作比类更加抽象的概念,类也可以看作模块。另一种理解是:把模块看作比类更加粗粒度的代码块,模块中包含多个类,多个类组成一个模块。
一个类只负责完成一个职责或者功能。也就是说,不要设计大而全的类,要设计粒度小、功能单一的类。换个角度来讲就是,一个类包含了两个或者两个以上业务不相干的功能,那我们就说它职责不够单一,应该将它拆分成多个功能更加单一、粒度更细的类。
一个类里既包含订单的一些操作,又包含用户的一些操作。而订单和用户是两个独立的业务领域模型,我们将两个不相干的功能放到同一个类中,那就违反了单一职责原则。为了满足单一职责原则,我们需要将这个类拆分成两个粒度更细、功能更加单一的两个类:订单类和用户类
如果判定一个类是否单一
public class UserInfo { private long userId; private String username; private String email; private String telephone; private long createTime; private long lastLoginTime; private String avatarUrl; private String provinceOfAddress; // 省 private String cityOfAddress; // 市 private String regionOfAddress; // 区 private String detailedAddress; // 详细地址 // ...省略其他属性和方法... }
上面类 可以说是满足单一模式 因为地址 是用户信息的一部分,也可以说不是 需要拆分成UserAddress 独立出来
评价一个类是否单一 并没有非常明确的,可以量化的指标。在设计时我们可以先设计出一个粗粒度的类 在后期随着业务扩展的时候再进行拆分,比如上面例子,业务扩展出另外一个子系统 需要用户支持共享和添加地址信息。
类是否是设计越单一越好
/** * Protocol format: identifier-string;{gson string} * For example: UEUEUE;{"a":"A","b":"B"} */ public class Serialization { private static final String IDENTIFIER_STRING = "UEUEUE;"; private Gson gson; public Serialization() { this.gson = new Gson(); } public String serialize(Map<String, String> object) { StringBuilder textBuilder = new StringBuilder(); textBuilder.append(IDENTIFIER_STRING); textBuilder.append(gson.toJson(object)); return textBuilder.toString(); } public Map<String, String> deserialize(String text) { if (!text.startsWith(IDENTIFIER_STRING)) { return Collections.emptyMap(); } String gsonStr = text.substring(IDENTIFIER_STRING.length()); return gson.fromJson(gsonStr, Map.class); } }
将序列化后反序列化拆分成2个类
public class Serializer { private static final String IDENTIFIER_STRING = "UEUEUE;"; private Gson gson; public Serializer() { this.gson = new Gson(); } public String serialize(Map<String, String> object) { StringBuilder textBuilder = new StringBuilder(); textBuilder.append(IDENTIFIER_STRING); textBuilder.append(gson.toJson(object)); return textBuilder.toString(); } } public class Deserializer { private static final String IDENTIFIER_STRING = "UEUEUE;"; private Gson gson; public Deserializer() { this.gson = new Gson(); } public Map<String, String> deserialize(String text) { if (!text.startsWith(IDENTIFIER_STRING)) { return Collections.emptyMap(); } String gsonStr = text.substring(IDENTIFIER_STRING.length()); return gson.fromJson(gsonStr, Map.class); } }
可能出现的问题是 序列化协议又json改为xml 但反序列化类也要随着修改 如果漏掉修改就会出序列化失败的问题 导致,拆分之后,代码的可维护性变差了。
什么时候考虑进行拆分
类中的代码行数、函数或者属性过多;类依赖的其他类过多,或者依赖类的其他类过多;私有方法过多;比较难给类起一个合适的名字;类中大量的方法都是集中操作类中的某几个属性。