GRASP,全称为General Responsibility Assignment Software Pattern,即通用职责分配软件模式,它由《UML和模式应用》(Applying UML and Patterns)一书做者Craig Larman提出。与其将它们称之为设计模式,不如称之为设计原则,由于它是站在面向对象设计的角度,告诉咱们怎样设计问题空间中的类与分配它们的行为职责,以及明确类之间的相互关系等,而不像GoF模式同样是针对特定问题而提出的解决方案。所以GRASP站在一个更高的角度来看待面向对象软件的设计,它是GoF设计模式的基础。数据库
GRASP是对象职责分配的基本原则,其核心思想是职责分配(Responsibility Assignment),用职责设计对象(Designing Objects with Responsibilities)。它包含以下9个基本模式:编程
1. 信息专家模式 (Information Expert Pattern)设计模式
(1) 问题:给对象分配职责的通用原则是什么?服务器
(2) 解决方案:将职责分配给拥有履行一个职责所必需信息的类,即信息专家。架构
(3) 分析:信息专家模式是面向对象设计的最基本原则。通俗点来说,就是一个类只干该干的事情,不应干的事情不干。在系统设计时,须要将职责分配给具备实现这个职责所须要信息的类。信息专家模式对应于面向对象设计原则中的单一职责原则。函数
2. 创造者模式 (Creator Pattern)spa
(1) 问题:谁应该负责产生类的实例?.net
(2) 解决方案:若是符合下面的一个或者多个条件,则可将建立类A实例的职责分配给类B:设计
B包含A;代理
B聚合A;
B拥有初始化A的数据并在建立类A的实例时将数据传递给类A;
B记录A的实例;
B频繁使用A。
此时,咱们称类B是类A对象的建立者。若是符合多个条件,类B聚合或者包含类A的条件优先。
(3) 分析:建立对象是面向对象系统中最广泛的活动之一,所以,肯定一个分配建立对象的通用职责很是重要。若是职责分配合理,设计就能下降耦合,提升设计的清晰度、封装性和重用性。一般状况下,若是对象的建立过程不是很复杂,则根据上述原则,由使用对象的类来建立对象。可是若是建立过程很是复杂,并且可能须要重复使用对象实例或者须要从外部注入一个对象实例,此时,能够委托一个专门的工厂类来辅助建立对象。建立者模式与各类工厂模式(简单工厂模式、工厂方法模式和抽象工厂模式)相对应。
3. 低耦合模式 (Low Coupling Pattern)
(1) 问题:怎样支持低的依赖性,减小变动带来的影响,提升重用性?
(2) 解决方案:分配一个职责,使得保持低耦合度。
(3) 分析:耦合是评价一个系统中各个元素之间链接或依赖强弱关系的尺度,具备低耦合的元素不过多依赖其余元素。此处的元素能够是类,也能够是模块、子系统或者系统。具备高耦合的类过多地依赖其余类,这种设计将会致使:一个类的修改致使其余类产生较大影响;系统难以维护和理解;系统重用性差,在重用一个高耦合的类时不得不重用它所依赖的其余类。所以须要对高耦合的系统进行重构。
类A和类B之间的耦合关系体现以下:A具备一个B类型的属性;A调用B的方法;A的方法包含对B的引用,如方法参数类型为B或返回类型为B;A是B的直接或者间接子类;B是一个接口,A实现了该接口。低耦合模式鼓励在进行职责分配时不增长耦合性,从而避免高耦合可能产生的不良后果。在进行类设计时,须要保持类的独立性,减小类变动所带来的影响,它一般与信息专家模式和高内聚模式一块儿出现。为了达到低耦合,咱们能够经过以下方式对设计进行改进:
在类的划分上,应当尽可能建立松耦合的类,类之间的耦合度越低,就越有利于复用,一个处在松耦合中的类一旦被修改,不会对关联的类形成太大波及;
在类的设计上,每个类都应当尽可能下降其成员变量和成员函数的访问权限;
在类的设计上,只要有可能,一个类型应当设计成不变类;
在对其余类的引用上,一个对象对其余对象的引用应当降到最低。
4. 高内聚模式 (High Cohesion Pattern)
(1) 问题:怎样使得复杂性可管理?
(2) 解决方案:分配一个职责,使得保持高内聚。
(3) 分析:内聚是评价一个元素的职责被关联和关注强弱的尺度。若是一个元素具备不少紧密相关的职责,并且只完成有限的功能,则这个元素就具备高内聚性。此处的元素能够是类,也能够是模块、子系统或者系统。
在一个低内聚的类中会执行不少互不相关的操做,这将致使系统难于理解、难于重用、难于维护、过于脆弱,容易受到变化带来的影响。所以咱们须要控制类的粒度,在分配类的职责时使其内聚保持为最高,提升类的重用性,控制类设计的复杂程度。为了达到低内聚,咱们须要对类进行分解,使得分解出来的类具备独立的职责,知足单一职责原则。在一个类中只保留一组相关的属性和方法,将一些须要在多个类中重用的属性和方法或完成其余功能所需的属性和方法封装在其余类中。类只处理与之相关的功能,它将与其余类协做完成复杂的任务。
5. 控制器模式 (Controller Pattern)
(1) 问题:谁应该负责处理一个输入系统事件?
(2) 解决方案:把接收或者处理系统事件消息的职责分配给一个类。这个类能够表明:
整个系统、设备或者子系统;
系统事件发生时对应的用例场景,在相同的用例场景中使用相同的控制器来处理全部的系统事件。
(3) 分析:一个控制器是负责接收或者处理系统事件的非图形用户界面对象。一个控制器定义一组系统操做方法。在控制器模式中,要求系统事件的接收与处理一般由一个高级类来代替;一个子系统须要定义多个控制器,分别对应不一样的事务处理。一般,一个控制器应当把要完成的功能委托给其余对象,它只负责协调和控制,自己不完成太多的功能。它能够将用户界面所提交的请求转发给其余类来处理,控制器能够重用,且不能包含太多业务逻辑,一个系统一般也不能设计一个统一的控制器。控制器模式与MVC模式相对应,MVC是一种比设计模式更加高级的架构模式。
6. 多态模式 (Polymorphism Pattern)
(1) 问题:如何处理基于类型的不一样选择?如何建立可嵌入的软件组件?
(2) 解决方案:当相关选择或行为随类型(类)变化而变化时,用多态操做为行为变化的类型分配职责。
(3) 分析:由条件变化引起同一类型的不一样行为是程序的一个基本主题。若是用if-else或switch-case等条件语句来设计程序,当系统发生变化时必须修改程序的业务逻辑,这将致使很难方便地扩展有新变化的程序。另外对于服务器/客户端结构中的可视化组件,有时候须要在不影响客户端的前提下,将服务器的一个组件替换成另外一个组件。此时可使用多态来实现,将不一样的行为指定给不一样的子类,多态是设计系统如何处理类似变化的基本方法,基于多态分配职责的设计能够方便地处理新的变化。在使用多态模式进行设计时,若是须要对父类的行为进行修改,能够经过其子类来实现,不一样子类能够提供不一样的实现方式,将具体的职责分配给指定的子类。新的子类增长到系统中也不会对其余类有任何影响,多态是面向对象的三大基本特性之一(另外两个分别是封装和继承),经过引入多态,子类对象能够覆盖父类对象的行为,更好地适应变化,使变化点可以“经得起将来验证”。多态模式在多个GoF设计模式中都有所体现,如适配器模式、命令模式、组合模式、观察者模式、策略模式等等。
7. 纯虚构模式 (Pure Fabrication Pattern)
(1) 问题:当不想破坏高内聚和低耦合的设计原则时,谁来负责处理这种状况?
(2) 解决方案:将一组高内聚的职责分配给一个虚构的或处理方便的“行为”类,它并非问题域中的概念,而是虚构的事务,以达到支持高内聚、低耦合和重用的目的。
(3) 分析:纯虚构模式用于解决高内聚和低耦合之间的矛盾,它要求将一部分类的职责转移到纯虚构类中,在理想状况下,分配给这种虚构类的职责是为了达到高内聚和低耦合的目的。在实际操做过程当中,纯虚构有不少种实现方式,例如将数据库操做的方法从数据库实体类中剥离出来,造成专门的数据访问类,经过对类的分解来实现类的重用,新增长的数据访问类对应于数据持久化存储,它不是问题域中的概念,而是软件开发者为了处理方便而产生的虚构概念。纯虚构能够消除因为信息专家模式带来的低内聚和高耦合的坏设计,获得一个具备更好重用性的设计。在系统中引入抽象类或接口来提升系统的扩展性也能够认为是纯虚构模式的一种应用。纯虚构模式一般基于相关功能的划分,是一种以功能为中心的对象或行为对象。在不少设计模式中都体现了纯虚构模式,例如适配器模式、策略模式等等。
8. 中介模式 (Indirection Pattern)
(1) 问题:如何分配职责以免两个(或多个)事物之间的直接耦合?如何解耦对象以下降耦合度并提升系统的重用性?
(2) 解决方案:分配职责给中间对象以协调组件或服务之间的操做,使得它们不直接耦合。中间对象就是在其余组件之间创建的中介。
(3) 分析:要避免对象之间的直接耦合,最经常使用的作法是在对象之间引入一个中间对象或中介对象,经过中介对象来间接相连。中介模式对应于面向对象设计原则中的迪米特法则,在外观模式、代理模式、中介者模式等设计模式中都体现了中介模式。
9. 受保护变化模式 (Protected Variations Pattern)
(1) 问题:如何分配职责给对象、子系统和系统,使得这些元素中的变化或不稳定的点不会对其余元素产生不利影响?
(2) 解决方案:找出预计有变化或不稳定的元素,为其建立稳定的“接口”而分配职责。
(3) 分析:受保护变化模式简称PV,它是大多数编程和设计的基础,是模式的基本动机之一,它使系统可以适应和隔离变化。它与面向对象设计原则中的开闭原则相对应,即在不修改原有元素(类、模块、子系统或系统)的前提下扩展元素的功能。开闭原则又可称为“可变性封装原则(Principle of Encapsulation of Variation, EVP)”,要求找到系统的可变因素并将其封装起来。如将抽象层的不一样实现封装到不一样的具体类中,并且EVP要求尽可能不要将一种可变性和另外一种可变性混合在一块儿,这将致使系统中类的个数急剧增加,增长系统的复杂度。在具体实现时,为了符合受保护变化模式,咱们一般须要对系统进行抽象化设计,定义系统的抽象层,再经过具体类来进行扩展。若是须要扩展系统的行为,无须对抽象层进行任何改动,只须要增长新的具体类来实现新的业务功能便可,在不修改已有代码的基础上扩展系统的功能。大多数设计原则和GoF模式都是受保护变化模式的体现。
【做者:刘伟 http://blog.csdn.net/lovelion】