文章目录一. 如何判断类的职责是否足够单一二. 类的职责是否设计得越单一越好开始学习一些经典的设计原则其中包括SOLID、KISS、YAGNI、DRY、LOD 等。本文主要学习单一职责原则的相关内容。单一职责原则的定义一个类只负责完成一个职责或者功能。也就是说不要设计大而全的类要设计粒度小、功能单一的类。比如一个类里既包含订单的一些操作又包含用户的一些操作。而订单和用户是两个独立的业务领域模型我们将两个不相干的功能放到同一个类中那就违反了单一职责原则。为了满足单一职责原则我们需要将这个类拆分成两个粒度更细、功能更加单一的两个类订单类和用户类。一. 如何判断类的职责是否足够单一大部分情况下类里的方法是归为同一类功能还是归为不相关的两类功能并不是那么容易判定的。如下举个例子创建一个UserInfo类publicclassUserInfo{privatelonguserId;privateStringusername;privateStringemail;privateStringtelephone;privatelongcreateTime;privatelonglastLoginTime;privateStringavatarUrl;privateStringprovinceOfAddress;// 省privateStringcityOfAddress;// 市privateStringregionOfAddress;// 区privateStringdetailedAddress;// 详细地址// ...省略其他属性和方法...}结合具体的应用场景说明如果在这个社交产品中用户的地址信息跟其他信息一样只是单纯地用来展示那 UserInfo 现在的设计就是合理的。如果这个社交产品发展得比较好之后又在产品中添加了电商的模块用户的地址信息还会用在电商物流中那我们最好将地址信息从 UserInfo 中拆分出来独立成用户物流信息或者叫地址信息、收货信息等。综上所述评价一个类的职责是否足够单一我们并没有一个非常明确的、可以量化的标准这是件非常主观的事情。持续重构实际上在真正的软件开发中我们也没必要过于未雨绸缪过度设计。所以我们可以先写一个粗粒度的类满足业务需求。随着业务的发展如果粗粒度的类越来越庞大代码越来越多这个时候我们就可以将这个粗粒度的类拆分成几个更细粒度的类。这就是所谓的持续重构。下面这几条判断原则比起很主观地去思考类是否职责单一要更有指导意义、更具有可执行性类中的代码行数200行、函数或属性过多10个以上会影响代码的可读性和可维护性我们就需要考虑对类进行拆分类依赖的其他类过多或者依赖类的其他类过多不符合高内聚、低耦合的设计思想我们就需要考虑对类进行拆分私有方法过多我们就要考虑能否将私有方法独立到新的类中设置为 public 方法供更多的类使用从而提高代码的复用性比较难给类起一个合适名字很难用一个业务名词概括或者只能用一些笼统的 Manager、Context 之类的词语来命名这就说明类的职责定义得可能不够清晰类中大量的方法都是集中操作类中的某几个属性比如在 UserInfo 例子中如果一半的方法都是在操作 address 信息那就可以考虑将这几个属性和对应的方法拆分出来。实际上 从另一个角度来看当一个类的代码读起来让你头大了实现某个功能时不知道该用哪个函数了想用哪个函数翻半天都找不到了只用到一个小功能要引入整个类类中包含很多无关此功能实现的函数的时候这就说明类的行数、函数、属性过多了。二. 类的职责是否设计得越单一越好为了满足单一职责原则是不是把类拆得越细就越好呢答案是否定的。Serialization 类实现了一个简单协议的序列化和反序列功能。/** * Protocol format: identifier-string;{gson string} * For example: UEUEUE;{a:A,b:B} */publicclassSerialization{privatestaticfinalStringIDENTIFIER_STRINGUEUEUE;;privateGsongson;publicSerialization(){this.gsonnewGson();}publicStringserialize(MapString,Stringobject){StringBuildertextBuildernewStringBuilder();textBuilder.append(IDENTIFIER_STRING);textBuilder.append(gson.toJson(object));returntextBuilder.toString();}publicMapString,Stringdeserialize(Stringtext){if(!text.startsWith(IDENTIFIER_STRING)){returnCollections.emptyMap();}StringgsonStrtext.substring(IDENTIFIER_STRING.length());returngson.fromJson(gsonStr,Map.class);}}拆成一个只负责序列化工作的 Serializer 类和另一个只负责反序列化工作的 Deserializer 类。publicclassSerializer{privatestaticfinalStringIDENTIFIER_STRINGUEUEUE;;privateGsongson;publicSerializer(){this.gsonnewGson();}publicStringserialize(MapString,Stringobject){StringBuildertextBuildernewStringBuilder();textBuilder.append(IDENTIFIER_STRING);textBuilder.append(gson.toJson(object));returntextBuilder.toString();}}publicclassDeserializer{privatestaticfinalStringIDENTIFIER_STRINGUEUEUE;;privateGsongson;publicDeserializer(){this.gsonnewGson();}publicMapString,Stringdeserialize(Stringtext){if(!text.startsWith(IDENTIFIER_STRING)){returnCollections.emptyMap();}StringgsonStrtext.substring(IDENTIFIER_STRING.length());returngson.fromJson(gsonStr,Map.class);}}虽然经过拆分之后Serializer 类和 Deserializer 类的职责更加单一了但也随之带来了新的问题。如果我们修改了协议的格式数据标识从“UEUEUE”改为“DFDFDF”或者序列化方式从 JSON 改为了 XML那 Serializer 类和 Deserializer 类都需要做相应的修改代码的内聚性显然没有原来 Serialization 高了。实际上不管是应用设计原则还是设计模式最终的目的还是提高代码的可读性、可扩展性、复用性、可维护性等。我们在考虑应用某一个设计原则是否合理的时候也可以以此作为最终的考量标准。参考《设计模式之美》–王争
阅读完成 · 觉得有帮助?