1

在软件设计中构思对象的职责、角色和协作,需要用到一些原则和模式,GRASP九大原则 -> SOLID六大原则 -> GOF23种设计模式,GRASP处于最上层(更一般化的原则,不只应用于面向对象设计),SOLID原则再进一步细化,GOF再根据这些原则进一步的归纳出更具体的模式。

软件设计在本质上是为了控制复杂度,降低”软件的熵“软件的复杂性在于除了要解决功能性需求,还要解决非功能性需求:可用性、可维护性、可扩展性、稳定性、高性能、数据一致性、容错性、可复用性、安全性、幂等性、兼容等等。

在常见的分层设计中,每一层都对上层屏蔽了内部的复杂度。同理,在类的设计中,类的复杂度也通过封装不蔓延到其他地方。

GRASP(General Responsibility Assignment Software Pattern),来源于:克雷·拉蒙.《Applying UML and Patterns》.1997,包含以下九个原则。

信息专家(Information Expert)

定义:如果一个类拥有执行某个职责所必需的信息,那么将这个职责分配给这个类。
优点:降低了类间耦合,使信息(知识)没有蔓延出去。

创建者(Creator)

谁应该负责创建一个类的实例?此模式回答了这个问题。
定义:如果符合下面的一个或者多个条件,则可将创建类A实例的职责分配给类B。
1.B包含或聚合了A;
2.B拥有初始化A的数据,并把该数据在创建A的实例时传递给A;
3.B记录A的实例;
4.B频繁使用A;
优点:降低了类间耦合,因为类B和类A已经存在耦合,所以并没有增加额外的耦合。

低耦合

耦合:评价一个系统中各个元素(类,模块,子系统)之间的依赖程度。以下是一些耦合关系的体现:
1.A具有一个B类型的属性(field);
2.A调用了B的方法;
3.A的方法包含对B的引用,比如方法参数为B,或返回类型为B;
4.A是B的子类;
5.B是一个接口,A实现了B接口;
以上这些耦合关系越多代表耦合程度越高。这些关系简单地说就是A对B的“感知”。
高耦合的缺点:一个类的修改会对其他类产生影响,容易产生遗漏和问题;系统难以维护和理解,复用性也很差。
降低耦合的一些方法:尽量减少对其他类的引用;提高方法和属性的访问权限;尽量使用组合/聚合原则来替代继承;多态也是一种降低耦合的方法,调用者只需要知道父类即可,不需要知道所有子类型,降低了类型耦合。
类间依赖是一种常见的耦合关系,尽量使用单向依赖,去除或弱化双向依赖,不使用循环依赖。

高内聚

内聚:是对元素职责的相关性和集中度的度量。
定义:即功能紧密相关的职责应该放在一个类里,并共同完成有限的功能。与单一职责和接口隔离原则是一致的。
优点:类的功能高内聚后复杂性就降低了,维护成本也就随之降低;同时提高了复用性。
低内聚的缺点:类要做许多不相关的工作,或需要完成大量的工作,导致类难以理解,难以复用,难以维护,经常被改动。
如下图,非内聚的类(或模块)包含了多个不相关业务的功能,看起来比较杂乱。对它进行职责拆分后,不同业务的功能放在不同的类(模块),高内聚之后的结构显得十分清晰。
高内聚图示

控制器(Controller)

定义:把接收或者处理系统事件消息的职责分配给一个类(这个类也可以是:子系统,或设备);
一个控制器应该处理一类事件,控制器要把完成的功能委托给业务层Service,它只负责协调和控制业务流程。
优点:控制器的核心是提供一个统一入口(比如外观模式),避免客户对系统内部进行耦合,很好的维护了职责边界。

多态

定义:当相关选择或行为随类型(类)变化而变化时,用多态操作为行为变化的类型分配职责。
优点:多态是面向对象设计的基本操作,它使未来的变化可以通过扩展新的子类解决,符合开闭原则。

纯虚构(Pure Fabrication)

定义:为了支持良好的内聚和低耦合以及复用性,将一组相关职责分配给一个虚构的类(这个类不是问题域中的概念)。比如数据库操作DAO,service,handler等。
优点:解耦,以及支持了高内聚和复用性。

间接(Indirection)

定义:配职责给中间对象(中介)以协调组件或服务之间的操作,使得它们不直接耦合。
优点:实现了类间的隔离和解耦。
有一种幽默的说法:“大多数设计问题都可以通过增加一层来解决,如果不行就再加一层。而性能问题则刚好相反,减少一层就能解决问题。”

受保护的变化(Protected Variations)

定义:找出预计有变化或不稳定的元素,为其创建稳定的“接口”而分配职责。
即考虑未来变化的扩展性,它是大多数程序设计的基础,是模式的基本动机之一,它使系统能够适应和隔离变化。与ETC原则一致,与面向对象的开闭原则相对应。


Cong
8 声望1 粉丝

Create value