GRASP设计模式文档格式.docx
- 文档编号:18168765
- 上传时间:2022-12-13
- 格式:DOCX
- 页数:15
- 大小:69.65KB
GRASP设计模式文档格式.docx
《GRASP设计模式文档格式.docx》由会员分享,可在线阅读,更多相关《GRASP设计模式文档格式.docx(15页珍藏版)》请在冰豆网上搜索。
entities
(classes,
modules,
function,
etc.)
open
extension,
but
closed
modification.
软件实体(模块,类,方法等)应该对扩展开放,对修改关闭。
Liskov
Substitution
(LSP)
OO设计的里氏替换原则
Functions
that
use
pointers
or
references
base
classes
must
able
objects
of
derived
without
knowing
it.
所有引用基类的地方必须能透明地使用其子类的对象。
Dependency
Inversion
(DIP)
OO设计的依赖倒置原则
A.
High
level
modules
not
depend
upon
low
modules.
Both
abstractions.
B.
Abstractions
details.
Details
高层模块不应该依赖于低层模块,二者都应该依赖于抽象
抽象不应该依赖于细节,细节应该依赖于抽象
TheInterfaceSegregationPrinciple(ISP)-OO设计的接口分隔原则
Clientsshouldnotbeforcedtodependuponinterfacesthattheydonotuse.
不能强迫用户去依赖那些他们不使用的接口。
包设计原则
包的内部关系方面(聚合性)的原则
Release
Reuse
Equivalency
(REP)
OO设计的重用发布等价原则
granule
reuse
is
the
release.
重用粒度等价于发布粒度。
Common
(CRP)
OO设计的全部重用原则
in
package
are
reused
together.
If
you
package,
them
all.
包的所有类被一起重用。
如果你重用了其中的一个类,就重用全部。
Closure
(CCP)
OO设计的共同封闭原则
together
against
same
kinds
changes.
change
affects
all
package.
一个包中所有的类应该对同一种类型的变化关闭。
一个变化影响一个包,便影响了包中所有的类。
包之间的关系方面(耦合性)的原则
Acyclic
Dependencies
(ADP)
OO设计的无环依赖原则
dependency
structure
between
packages
directed
acyclic
graph
(DAG).
That
is,
there
no
cycles
structure.
包之间的依赖结构必须是一个直接的无环图形(DAG)。
也就是说,在依赖结构中不允许出现环(循环依赖)。
Stable
(SDP)
OO设计的稳定依赖原则
dependencies
design
direction
stability
packages.
A
only
stable
it
is.
GRASP设计模式-概要篇
GRASP是GeneralResponsibilityAssignmentSoftwarepatterns(通用职责分配软件模式)的简称,它的核心思想是“职责分配(ResponsibilityAssignment)”。
GRASP提出了几个基本原则,用来解决面向对象设计的一些问题。
CraigLarman氏在《ApplyingUMLandPatterns》一书中提出了GRASP设计模式的概念。
作者称其为设计模式,其实,更好的理解应该为设计原则。
因为,与GoF等设计模式不同的是,GoF等设计模式是针对特定问题而提出的解决方法,而GRASP则是站在面向对象设计的角度,告诉我们怎么样设计问题空间中的类与它们的行为责任,以及明确类之间的相互关系等等。
GRASP可以说是GoF等设计模式的基础。
GRASP是GeneralResponsibilityAssignmentSoftwarepatterns(通用职责分配软件模式)的简称,它的核心思想是“职责分配(ResponsibilityAssignment)”,用职责设计对象:
"
DesigningObjectswithResponsibilities"
。
它包含了9个基本模式:
1,信息专家(Informationexpert)
2,创建者(Creator)
3,高内聚(HighCohesion)
4,低耦合(Lowcoupling)
5,控制器(Controller)
6,多态性(Polymorphism)
7,纯虚构(PureFabrication)
8,间接性(Indirection)
9,变化预防(ProtectedVariations)
GRASP的主要特征:
-对象职责分配的基本原则。
-主要应用在分析和建模上。
GRASP的核心思想的理解:
自己干自己的事(职责的分配)
自己干自己的能干的事(职责的分配)
自己只干自己的事(职责的内聚)
面向对象设计
所谓面向对象设计,就是在系统设计的过程中,通过把系统分成相对独立但又互相联系的对象组合的一种设计方法。
对象具有属性和行为,对象间通过消息进行交互(协作)。
面向对象设计一般有以下几个关键步骤:
1,发现对象。
找出系统应该由哪些对象构成。
2,对象的属性。
对象具有哪些属性。
3,对象的行为。
对象具有哪些行为,或者说对象需要做什么,它的职责是什么。
4,对象的关系。
对象与对象之间的关系是什么,怎样进行交互,协作等等。
发现对象
对象的发现超出了本文的讨论范围。
我们简单地介绍一下对象发现的过程与手段。
一般意义上的对象是现实世界上物体的抽象。
也就是说,现实世界里有什么物体,就有什么对象;
物体存在什么属性,对象就有什么属性。
我们可以用“名词筛选法”来发现系统的对象。
比如,一个学生考试成绩管理系统,有以下简单的用例:
-管理员创建题库(把题条加入题库)
-系统根据管理员输入的某些条件随机生成试题
-学生成绩入库与管理
我们可以通过字面意思找出名词,就可以找出“管理员”,“题条”,“题库”,“试题”,“学生”,“学生成绩”等几个对象。
一般通过这种方法(名词筛选法)就可以找出系统的绝大部分对象。
对象行为
行为是对象应该执行的动作,也就是对象的职责。
对象具有哪些职责呢?
相对于上面所说的“名词筛选法”,可以简单地用“动词筛选法”来发现“对象的行为”。
比如,上面的“学生考试成绩管理系统”一例中,有“创建题库”,“输入(条件)”,“生成试题”,“成绩入库”,“成绩管理”等动词,也就是说,系统的对象至少具有以上这些行为(或职责)。
有时,我们可能还会发现某些“行为”的粒度过大,这时,可以通过进一步细化用例的描述,来发现更多更细的“行为”。
这里不再详述。
问题1:
找出对象的行为(职责)之后,怎么样分配这些行为呢?
也就是说怎么确认“行为”属于哪个对象呢?
对象关系
系统的所有对象不可能是一个个单独存在毫无关系的个体,它们或多或少的有着各种联系(协作关系)。
问题2:
如果2个对象之间有协作关系,他们之间最好通过什么样的方式协作呢?
对象扩展特性
问题3:
已经被抽象出来的对象,如何面对将来可能发生的变化呢?
GRASP提出9个基本模式,用于解决以上设计过程中遇到的各种问题。
GRASPInformationExpertPattern-Grasp之信息专家模式
问题:
当我们为系统发现完对象和职责之后,职责的分配原则(职责将分配给哪个对象执行)是什么?
解决方案:
职责的执行需要某些信息(information),把职责分配给该信息的拥有者。
换句话说,某项职责的执行需要某些资源,只有拥有这些资源的对象才有资格执行职责。
这有点类似现实世界的“有能者为之”的概念。
你有建筑知识,可以去执行盖楼的职责;
你有法律知识,可以去裁判案件等等。
满足了面向对象设计的封装性的设计,一般情况下都会满足InformationExpert模式。
因为InformationExpert是对类的属性(信息),以及对类的属性的操作的封装,它符合对象封装性的概念。
优点:
-信息的拥有者类同时就是信息的操作者类,可以减少不必要的类之间的关联。
-各类的职责单一明确,容易理解
InformationExpert例
为了说明问题,我们使用“学生成绩管理系统”中的用例1来说明。
用例1:
再细化一下:
-管理员创建题库(把题条加入题库):
如果题库中已经存在所给的题条,则退出,否则加入题条。
这样就存在3个对象:
管理员用户User,题条SubjectItem,题库SubjectLibrary
2个职责:
判断(新加入的题条是否与题库某题条相等),加入(题条的加入)
这2个职责究竟应该由哪个对象执行?
我们使用InformationExpert模式来分析。
1,判断2个题条是否相等,只要判断题条的ID属性(或其它属性)是否相等就可以了。
题条的ID是属于题条的,所以对它的操作应该放在题条SubjectItem里。
2,题条的加入需要操作的数据有2部分,一部分是新加入的题条本身,另一部分是题库(加入到题库),题条是题库的一部分,所以题条的加入应该放在题库SubjectLibrary里完成。
如果把以上2个职责放在第三方类中,无疑增加了它们与第三方类之间的耦合关系。
GRASPCreatorPattern-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模式,先为它们设计好具有阶层关系的类图,如下:
因为MyMenu,MyToolBar,MyDialog由MainWindow所包含,MyTextbox,MyButton被MyDialog包含,MainWindow由Main类调用,
根据Creator模式所提倡的方法,它们的实例的创建职责的分配应该是:
MainWindow的实例由Main创建
MyMenu,MyToolbar,MyDialog的实例由MainWindow创建,
MyTextbox,MyButton的实例由MyDialog创建。
反过来,如果MyMenu,MyToolBar,MyDialog等实例的创建都放在Main类里,那么Main就跟它们产生一种“关联”关系,如果MyMenu,MyToolBar,MyDialog等发生修改,Main也不得不跟着一起修改,也就是说大大增强了Main类跟它们之间的耦合关系;
而Main类本身,也聚集了多余的实例创建功能,降低了Main类的聚合性。
GRASPHighCohesionPattern-GRASP之高内聚模式
高内聚模式(HighCohesion)是GRASP模式中为降低类的复杂程度,简化控制而提出的面向对象设计的原则性模式。
高内聚(HighCohesion)与低耦合(LowCoupling)模式是GRASP其他模式的根本。
怎么做才能降低类的复杂程度,简化控制?
HighCohesion模式所提倡的解决方案:
紧密相关的功能(职责)应该分配给同一个类。
所谓内聚,是指单个物体(类)内部的功能聚集度。
比如,只包含有相互关联的功能的类,具有高内聚性,同时,它的外部表现(作用,意图)也就明显;
反之,如果一个类由一些不相关的功能构成,它的内聚性就低,它的外部表现就不明显,一方面很难理解它的作用和意图,另一方面,一旦需求变化,扩展性就差。
在现实世界里,高内聚(HighCohesion)表现在“各司其职”上,也就是说自己只干跟自己相关的工作,别人的工作让别人做。
比如,电视机只有信息传播的功能,冰箱只有冷藏冷冻的功能,它们就是一个功能高内聚的个体。
为什么不把电视机与冰箱的功能做在一起呢?
因为做在一起的话,一方面,只需要电视或冰箱功能的消费者却不得不同时购买它们的整合体,而且消费者如果想换代电视机时,冰箱也只有一起换代;
另一方面,如果厂家需要升级电视功能,也不得不考虑怎么整合原来的冰箱功能。
也就是说功能低内聚的产品,不利于消费者使用,不利于生产者维护,不利于产品本身的升级换代。
同样,反映到软件设计上,低内聚的类存在使用难,维护升级难的缺点。
高内聚(HighCohesion)与低耦合(LowCoupling)是GRASP模式的核心概念,是其它GRASP模式的根本。
优秀的面向对象设计,一般都遵从[高内聚,低耦合]原则。
应用HighCohesion模式的好处
-聚集相关功能,结构清晰,容易理解
-只聚集相关功能,使得类的职责单一明确,从而降低类的复杂程度,使用简单
GRASPLowCouplingPattern-GRASP之低耦合模式
低耦合模式(LowCoupling)是GRASP模式中为降低类之间的关联程度,适应可变性而提出的面向对象设计的原则性模式。
怎么做才能降低类之间关联程度,能适应需求的变化呢?
LowCoupling模式所提倡的解决方案
为类分配职责时,应该尽量降低类之间的关联关系(耦合性)。
亦即,应该以降低类之间的耦合关系作为职责分配的原则。
所谓耦合,是指多个物体(类)之间的物理或者意思上的关联程度。
在面向对象方法中,类是最基本的元素,耦合主要指不同类之间相互关联的紧密程度。
面向对象里的关联,主要指一个类对另一个类的调用,聚合(包含),参数传递等关系。
比如,所谓2个关联得非常紧密的类(高耦合),是指其中一个类发生变化(修改)时,另一个类也不得不跟着发生变化(修改)。
面向对象设计要求类之间满足“低耦合”原则,它是衡量一个设计是否优良的的一个重要标准,因为“低耦合”有助于使得系统中某一部分的变化对其它部分的影响降到最低程度。
-独立性,有利于重用。
-适应需求变化,一旦发生变化时,可以把影响缩小到最小范围。
内聚与耦合的辩证关系
1,一方面,高内聚要求把紧密关联的功能(职责)聚集在同一个类中,防止功能的扩散和类的无谓增加,从而减少类之间的关联,降低类之间的发生耦合的机率。
2,另一方面,高内聚要求把不相关的功能分散到不同的类,类增加了,势必造成相互关联类的增加,从而增大类之间发生耦合的机率。
面向对象设计,应该考虑效率,实现难度等因素,同时兼顾高内聚(HighCohesion)与低耦合(LowCoupling)性。
GRASPControllerPattern-GRASP之控制器模式
控制器模式(Controller)是GRASP模式中解决事件处理职责问题的模式。
在UI层之外,应该由哪个类来处理(控制)系统操作(事件)呢?
或者说,当触发一个系统事件时,应该把对事件的处理职责分配给UI层之外的哪个累呢?
Controller模式所提倡的解决方案
把系统事件的处理职责分配给Controller(控制器)类。
担当Controller(控制器)类角色的候补类可能为:
-系统全体,设备,子系统等的表现类(FacadeController)
-系统事件发生的用例的控制类,通常被命名为Handler,Coordinator,Session等(用例或Session的控制器)。
整个系统事件都使用同一个控制器。
Controller模式相当于著名的MVC设计模式的C(Controller)部分。
类似于J2EE核心模式中的FrontController模式(我们会在其它文章中介绍FrontController模式)。
Controller模式提倡用一个专门的类来处理所有的系统事件。
或者说Controller模式把所有系统事件的处理职责分配给一个专门的类集中处理。
应用Controller模式的好处
应用Controller模式的系统,对系统事件进行集中处理,所以:
-防止同类职责的分散。
满足高内聚,低耦合原则。
-有利于共通处理(前处理,后处理等)。
-变化的高适应能力。
能够把变化的修改范围控制在最小范围(控制器)之内。
Controller模式的应用例
MVC模式。
GRASPIndirectionPattern-GRASP之间接性模式
间接性模式(Indirection)是GRASP模式中解决类的关联问题的模式。
为了避免类之间的直接关联,应该给什么样的类分配“关联”责任?
Indirection模式所提倡的解决方案
当多个类之间存在复杂的消息交互(关联)时,Indirection模式提倡类之间不直接进行消息交互处理(非直接),而是导入第三方类,把责任(多个类之间的关联责任)分配给第三方类,降低类之间的耦合程度。
应用Indirection模式的好处
-高内聚。
通过把“关联”的功能分散到第三方类,原来的类可以更加关注自身功能的实现。
-低耦合。
原本关联类之间不直接关联,降低类之间的耦合性。
-高重用性。
第三方类对“关联”功能的集中处理,与原来的类对自身功能的专注,有利于类的重用。
Indirection模式的应用例
应用Indirection模式的一个最好范例是GoF的Mediator(中介者)模式。
GRASPPolymorphismPattern-GRASP之多态性模式
多态性模式(Polymorphism)是GRASP扩展模式的一种,它通过多态操作把基于类型的可变行为的定义职责分配给行为发生的类。
根据类型(类)的不同而发生变化的行为的定义职责,应该分配给谁?
问题比较抽象难懂,我们通过举例来解释一下。
比如物体的移动行为,不同的物体有不同的移动方法,比方说汽车与人的移动方法不一样。
在面向对象设计中,怎么样分配此类行为的定义职责呢?
或者说,此类行为应该在哪定义怎么定义呢?
Polymorphism模式所提倡的解决方案
Polymorphism模式提倡通过多态操作把基于类型的可变行为的定义职责分配给行为发生的类。
又是一个抽象的概念。
我们来解释一下。
多态性是面向对象的重要概念之一。
所谓多态性,简单地说,就是具有同一接口的不同对象对相同的消息具有不同的行为。
或者说同一消息作用于不同的对象,而产生不同的结果。
传统的设计方法,当类型发生变化时,利用条件判断语句对类型进行判断,然后执行不同的行为。
Polymorphism模式把各变化的“行为”定义职责分别分配给具有相同操作行为界面的通用接口的实现子类,利用多态性适应行为的可变性。
应用Polymorphism模式的好处
-避免重复代码
-避免重复的分歧条件
-易扩展。
只要实现了统一的通用接口,便可实现行为的扩展
Polymorphism模式的应用例
上面的例子:
物体的移动行为,应用Polymorphism设计模式,它的类图便是:
如果我们需要扩展“移动”行为,只需简单地创建一个实现IRunner接口的类。
其他应用Polymorphism模式的例
设计模式之Com
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- GRASP 设计 模式