讲解一些经典的设计原则,诸如SOLID KISS YAGNI DRY OLD
主要目的就是理解,而且会用,不然很多时候,对这个原则理解的不够深入,从而出现了教条主义的错误,太过于死扣
首先就是单一职责原则(SRP):
单一职责原则的全拼是Single Responsibility Principle 缩写为SRP,简单的描述为一个类或者一个模块只负责完成一个职责
虽然上面的说明了这个原则适用于类和模块,但是我们主要还是从类的设计角度来说明这个设计原则
这个原则总体理解很简单,就是一个类只负责完成一个功能或者一个职责,不要设计大而全的类,要设到要做到粒度小,功能单一的类,如果一个类包含了多个不相干的功能,那么就应该把它拆成多个类
但是很多时候,没法直接去判断一个类是否是职责单一的,比如 下面的UserInfo类,这个类看起来是职责单一的
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; // 详细地址 // …省略其他属性和方法… } |
但是,也有一种观点,认为UserInfo中不应该包含Address相关的信息,应该进行拆分,拆分为Address和User类,拆分后的类的职责更加单一,但是如果Address没有特殊含义,只是表明用户的所在地址,那么现在的UserInfo类已经够用了
但未来如果用户的地址可能作为用户的收货地址,那么我们就需要将我的Address类拆分出来同样,如果公司还开发了其他的社交产品,又希望能够统一账号登录,那么我们还需要将user类当中的email以及telephone这两个属性拆分出来作为登陆校验类
判断一个类它的职责是否单一是一种非常主观的问题,所以说我们可以在开发初期先写一个粗粒度的类,随着业务的发展一步步进行拆分,产生更加细粒度的类,让他职责更加单一
同样我们可以从一些侧面角度来看一个类它是否职责单一
1.类中的代码函数或者属性函数过多,导致降低了代码的可读性,这时候就有必要去拆分
2.类所依赖的其他类过多,导致偶合度较高,这时候应该对他进行拆分
3.如果一个类它所包含的功能无法用一个名词去形容,那么可以考虑将它拆成多个类
4.大量方法都是在操纵类中的几某几个属性,那么我们可以把这某几个属性单独提取出来,作为一个类就比如说我们User类当中的address
5.私有方法过多,我们要考虑能不能将私有方法提取出来,作为一个新的类提高代码复用性
当然,这都是一些从侧面角度去量化一个类是否值得去拆分,其实是否符合单一职责原则,还是依赖于开发者的主观思考,项目做多了,自然就知道了
类的职责是否是越单一越好?
/**
* 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); } } 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); } } |
当然并非越单一越好,比如把上面的Serialization类拆分为两个单独的类,虽然经过拆分后,Serializer类和Deserializer类职责单一了,但是在修改的时候,需要修改两个类了,达不到最低需求的内聚性,也是不合适的
今天的重点总结下
如何理解单一职责原则?
就是在一个类当中,尽可能只包一个单一的职责,从而做到高内聚低耦合和不要设计大而全的类,要设计功能单一的类
如何判断类的职责是否足够单一?
这是一个开发者主观的问题,但是我们可以从一些侧面去看一个类是否足够职责单一
1.类中的代码或者函数 属性过多
2.类所依赖的其他类过多
3.类中的某几个属性一直被调用
4.私有方法过多
5.无法用一个名词去描述这个类
类的职责是否越单一越好?
答案是否定的,如果拆分的过于细致,降低代码的内聚性,从而导致代码的可维护性降低