GRASP九大原则、SOLID七大原则、GOF23种设计模式这三类设计原则模式中。GRASP处于最上层,SOLID基于它再进一步细化阐述,GOF再根据这些原则进一步的归纳出更具体的模式。 GoF模式是针对特定问题而提出的解决方案,而GRASP站在一个更高的角度来看待面向对象软件的设计,它是GoF设计模式的基础。GRASP是对象职责分配的基本原则,其核心思想是职责分配,用职责设计对象。
如果某个类拥有执行某个职责所必需的的信息的话,那么将这个职责分配给这个类。
当我们不确定某个职责该分配给类A还是类B的时候,我们可以遵循这个原则。这个设计原则和单一设计原则不同,单一职责原则考虑的是单个类中的职责是否都属于一类职责。而信息专家模式考虑则是该把该同一类职责放进类A还是类B中。假设我们有一个长方形Rectangle类(类中有width和height属性)和一个Measure类,我们应该把getArea()方法放进Rectangle中去,还是将width和height参数传给Measure类,在Measure中实现getArea()呢?依照该准则,既然Rectangle方法已经有了实现getArea()所必须的属性的话,那么就把该把getArea()方法放进Retangle类中。同理如果有一个计算属性呢?假设是长宽高比例widthHeightRatio的话,也遵循该原则。==这个原则和DDD设计思想当中的充血模型是一致的,大家可以了解一下。==
如果符合下面的一个或者多个条件,则可将创建类A实例的职责分配给类B
在面向对象的设计当中,无法避免去创建对象。假设对象B创建对象A,那么对象B就产生了与对象A的耦合。而这种耦合是无法消除的,即使你将创建对象A的职责分配给对象C,这种耦合还是存在的,只是从对象B转移到对象C上,系统内还是依然存在这个耦合,无法避免。那么当我们无法消除耦合的时候,我们应该考虑的是如何降低这个耦合的耦合度。这个原则给出了指导方针。以上的几个条件潜在的表明了,其实B已经对A有了耦合,既然B已经存在了对A的耦合,那么我们不妨再将创建A的职责分配给他。这样分配的话,系统内仅存在一个A与B的耦合。如果将创建A的职责分配给C的话,那么系统内就会存在B与A(B包含A、B频繁使用A等条件)和C与A这两个耦合。在JDK的Map中Entry类的创建职责就分配给了持有它的Map。还有一个比较经典的例子就是Order创建SKU。
耦合是评价一个系统中各个元素(类、模块、子系统)之间依赖的程度,而良好的设计应该尽可能降低这个程度。 以下是一些耦合关系的体现:
在以上的这些耦合条件中,出现得越多代表耦合程度越高。这些条件简单笼统的来说就是A对B的“感知”。这种感知体现在对象属性、方法参数、方法返回值以及接口上面。高耦合的类过多地依赖其他类,这种设计将会导致:一个类的修改导致其他类产生较大影响,系统难以维护和理解。在重用一个高耦合的类时不得不重用它所依赖的其他类,系统重用性差。如何降低耦合的程度有以下一些方法:尽量减少对其他类的引用,提高方法和属性的访问权限,尽量使用组合/聚合原则来替代继承。 其实面向对象编程中的多态就是一种降低类型耦合的方法,如果没有多态的话,我们的方法需要知道所有子类类型,而多态的话只需要知道父类即可。降低了类型耦合。
即功能性紧密相关的职责应该放在一个类里,并共同完成有限的功能。这点与SOLID原则当中的单一职责和接口隔离是一致的。
把接收或者处理系统事件消息的职责分配给一个类。这个类可以代表:整个系统、设备或者子系统;系统事件发生时对应的用例场景,在相同的用例场景中使用相同的控制器来处理所有的系统事件。
当相关选择或行为随类型(类)变化而变化时,用多态操作为行为变化的类型分配职责。
将一组高内聚的职责分配给一个虚构的或处理方便的“行为”类,它并不是问题域中的概念,而是虚构的事物,以达到支持高内聚、低耦合和复用。
OO设计中的领域模型是对领域内的概念或现实世界中的对象的模型化表示。创建领域模型的关键思想是减小软件人员的思维与软件模式之间的表示差异。因此,在OO设计时,系统内的大多数类都是来源于现实世界中的真实类。然而,在给这些类分配职责时,有可能会遇到一些很难满足低耦合高内聚的设计原则。纯虚构模式对这一问题给出的方案是:给人为制造的类分配一组高内聚的职责,该类并不代表问题领域的概念,而代表虚构出来的事物。比较明显的一个例子就是适配器模式,通过虚构出适配器这么一个概念来解耦两个对象之间的耦合。 许多项目都需要对数据库进行操作,将系统中的一些对象进行持久化。信息专家模式给出的建议是将持久化的职责分配给具体的每一个模型类。但是这种建议已经被证明是不符合高内聚低耦合原则的。于是,现在的做法往往会在项目中加入类似于DAO或者Repository这样的类。这些类在领域模型中是并不存在的。
分配职责给中间对象以协调组件或服务之间的操作,使得它们不直接耦合。中间对象就是在其他组件之间建立的中介。
找出预计有变化或不稳定的元素,为其创建稳定的“接口”而分配职责。
https://juejin.cn/post/6844903925863170055