GRASP(中文版)
——General Responsibility Assignment Software patterns(通用职责分配软件模式) 它的核心思想是“职责分配(Responsibility Assignment)”。GRASP提出了几个基本原则,用来解决面向对象设计的一些问题。
Craig Larman氏在《Applying UML and Patterns》一书中提出了GRASP设计模式的概念。作者称其为设计模式,其实,更好的理解应该为设计原则。因为,与GoF等设计模式不同的是,GoF等设计模式是针对特定问题而提出的解决方法,而GRASP则是站在面向对象设计的角度,告诉我们怎么样设计问题空间中的类与它们的行为责任,以及明确类之间的相互关系等等。GRASP可以说是GoF等设计模式的基础。
GRASP概要
它包含了9个基本模式:
1,信息专家(Information expert) 2,创建者(Creator) 3,高内聚(High Cohesion) 4,低耦合(Low coupling) 5,控制器(Controller) 6,多态性(Polymorphism) 7,纯虚构(Pure Fabrication) 8,间接性(Indirection)
9,变化预防(Protected Variations)
GRASP的主要特征:
? 对象职责分配的基本原则。 ? 主要应用在分析和建模上。
GRASP的核心思想的理解:
自己干自己的事(职责的分配)
自己干自己的能干的事(职责的分配) 自己只干自己的事(职责的内聚)
面向对象设计
所谓面向对象设计,就是在系统设计的过程中,通过把系统分成相对独立但又互相联系的对象组合的一种设计方法。
对象具有属性和行为,对象间通过消息进行交互(协作)。
面向对象设计一般有以下几个关键步骤:
1, 发现对象。找出系统应该由哪些对象构成。 2, 对象的属性。对象具有哪些属性。
3, 对象的行为。对象具有哪些行为;或者说对象需要做什么,它的职责是什么。 4, 对象的关系。对象与对象之间的关系是什么,怎样进行交互,协作等等。
发现对象
对象的发现超出了本文的讨论范围。我们简单地介绍一下对象发现的过程与手段。 一般意义上的对象是现实世界上物体的抽象。也就是说,现实世界里有什么物体,就有什么对象;物体存在什么属性,对象就有什么属性。 我们可以用“名词筛选法”来发现系统的对象。
比如,一个学生考试成绩管理系统,有以下简单的用例: - 管理员创建题库(把题条加入题库)
- 系统根据管理员输入的某些条件随机生成试题 - 学生成绩入库与管理
我们可以通过字面意思找出名词,就可以找出“管理员“,“题条”,“题库”,“试题”,“学生”,“学生成绩”等几个对象。
一般通过这种方法(名词筛选法)就可以找出系统的绝大部分对象。
对象行为
行为是对象应该执行的动作,也就是对象的职责。对象具有哪些职责呢?相对于上面所说的“名词筛选法”,可以简单地用“动词筛选法”来发现“对象的行为”。 比如,上面的“学生考试成绩管理系统”一例中,有“创建题库”,“输入(条件)”,“生成试题”,“成绩入库”,“成绩管理”等动词,也就是说,系统的对象至少具有以上这些行为(或职责)。 有时,我们可能还会发现某些“行为”的粒度过大,这时,可以通过进一步细化用例的描述,来发现更多更细的“行为”。这里不再详述。 问题1:找出对象的行为(职责)之后,怎么样分配这些行为呢?也就是说怎么确认“行为”属于哪个对象呢?
对象关系
系统的所有对象不可能是一个个单独存在毫无关系的个体,它们或多或少的有着各种联系(协作关系)。
问题2:如果2个对象之间有协作关系,他们之间最好通过什么样的方式协作呢?
对象扩展特性
问题3:已经被抽象出来的对象,如何面对将来可能发生的变化呢?
GRASP提出9个基本模式,用于解决以上设计过程中遇到的各种问题。
GRASP Information Expert Pattern - Grasp之信息专家模式
信息专家模式(Information Expert)是GRASP模式中解决类的职责分配问题的最基本的模式。 问题:
当我们为系统发现完对象和职责之后,职责的分配原则(职责将分配给哪个对象执行)是什么?
解决方案:
职责的执行需要某些信息(information),把职责分配给该信息的拥有者。
换句话说,某项职责的执行需要某些资源,只有拥有这些资源的对象才有资格执行职责。 这有点类似现实世界的“有能者为之”的概念。你有建筑知识,可以去执行盖楼的职责;你有法律知识,可以去裁判案件等等。
满足了面向对象设计的封装性的设计,一般情况下都会满足Information Expert模式。因为Information Expert是对类的属性(信息),以及对类的属性的操作的封装,它符合对象封装性的概念。
优点:
- 信息的拥有者类同时就是信息的操作者类,可以减少不必要的类之间的关联。 - 各类的职责单一明确,容易理解 Information Expert例
为了说明问题,我们使用“学生成绩管理系统”中的用例1来说明。 用例1:
- 管理员创建题库(把题条加入题库) 再细化一下:
- 管理员创建题库(把题条加入题库):如果题库中已经存在所给的题条,则退出,否则加入题条。
这样就存在3个对象:管理员用户User,题条SubjectItem,题库SubjectLibrary 2个职责:判断(新加入的题条是否与题库某题条相等),加入(题条的加入)
这2个职责究竟应该由哪个对象执行? 我们使用Information Expert模式来分析。
1, 判断2个题条是否相等,只要判断题条的ID属性(或其它属性)是否相等就可以了。
题条的ID是属于题条的,所以对它的操作应该放在题条SubjectItem里。 2, 题条的加入需要操作的数据有2部分,一部分是新加入的题条本身,另一部分是题库(加
入到题库),题条是题库的一部分,所以题条的加入应该放在题库SubjectLibrary里完成。
如图:
如果把以上2个职责放在第三方类中,无疑增加了它们与第三方类之间的耦合关系。
GRASP Creator Pattern - GRASP之创建者模式
创建者模式(Creator)是GRASP模式中解决类的实例的创建职责问题的模式。
问题
类的实例的创建职责,应该分配给什么样的类?或者说类的实例应该由谁创建?
Creator模式所提倡的解决方案
以下条件之一为真的情况,类A的实例的创建职责就分配给类B。 1, B包含A 2, B聚集A
3, B记录A
4, B频繁使用A
5, B有A初始化数据
Creator模式提倡类的实例(对象)创建职责由聚集或包含该对象的对象创建。
注:Creator模式只是一个原则,如果类A,B之间没有包含或聚集关系,应该先考案是否有“B记录A”,或者“B有A初始化数据”的关系,然后是“B频繁使用A”的关系。另外,作为代替方案,一般的采用工厂(Factory)创建方案。
如果不遵循Creator模式,把类的实例的创建职责交给无关的类,类之间的关系变得复杂化,降低系统的可维护性和可扩展性。
一般来说,应用Creator模式,可以从上之下设计好类之间的包含或聚集关系阶层图,让每个类负责创建自己包含的类的实例。
应用Creator模式的好处
- - -
整个结构清晰易懂
有利于类或组件的重用 防止职责的分散
- 降低耦合性
Creator模式的应用例
为了更清楚地说明Creator模式,我们举一个GUI的例子:
有一个用户窗口MainWindow,包含Menu,ToolBar,Dialog等,Dialog上布置有Textbox,Button等元素。
我们应用Creator模式,先为它们设计好具有阶层关系的类图,如下: