通用责任分配软件模式
Gerneral Responsibility Assignment Software Patterns
主要作用是指导 对象责任分配
责任:责任是类间的一种合约或是义务。责任可以包括行为、数据、对象创建等
责任=知道责任+行为责任
责任与方法的区别:责任不是类的方法,类的方法是用来实现类的责任的;责任的分配可以反应在协作图或顺序图中。
GRASP系列模式共分为9种。
2.1 Information Expert(信息专家)
信息专家原则:如果某个类在某方面具有完整的信息,足以实现某个责任,就将这个责任分配给这个类,这个类就是所谓的信息专家。
例子:购物车系统中,我们要让商品Item在购物车类只出现一次,如何分配这个责任?
解答:两个商品是依赖商品编码(ProductID)来标识的,那么具有ProductID的类 Item类就要包括检测责任,而购物车ShoppingCar类就具有将相同商品的数量加1的责任。
2.2 Creator(创造者)
应用情况符合下条件之一,类A应该具有创建类B的责任:
(1)a是b的聚合;
(2)a是b的容器;
(3)a有初始化b的数据;
(4)a记录b的实例
(5)a频繁使用b
凡事不符合上述条件的,不要设计类间耦合。
例子:出货单是物品的容器,所以出货单应该具有创建物品的责任。
2。3 Low Coupling(低耦合)
低耦合的作用很重要:
(1)使得一个类修改对其他类的影响降到最低;
(2)使系统维护变得更加容易;
(3)使得类更容易被理解
下列情况让A,B两个类产生耦合:
(1)a具有b的一个属性;
(2)a调用b对象的方法;
(3)a的方法包括对b的引用,例如返回的是b类型或参数是b类型;
(4)a是b的子类,或者a是b的实现类;
不对陌生人说话原则
拇指规则:
(1)如果a已经与b有连接,如分配责任a给b不合适,那么分配责任b给a
(2)两个模块中的内部类间连接是一个大错误。
2。4 High Cohesion(高内聚)
高内聚的目的是提高设计类的重用性,并控制类设计的复杂程度。
我们要努力分解类,使得分解出来的类具有独立的责任。
高内聚强调的宗旨是:类只处理与模块相关的功能,它与其它类合作共同完成任务。
eg:有一个订货类,现在要增加用于支持存取数据到Excel表中以支持不同数据来源的责任,这个责任应该加入这个订货类嘛?
因为订货详情和数据存取不是一个概念,因此一个高内聚的类设计就会再新建一个 订货数据存取类 。
高内聚的优点:
(1)易于实现类的重用
(2)使得维护工作更简单
(3)高内聚使得系统模块化,支持团队工作
2。5 Controller 控制器
通常将接收和处理系统事件的职责分配给以下类:
(1)能全面代表系统 设备或者子系统的类
(2)可以代表系统事件发生时用例发生情景的类
(3)代表某些卷入真实世界应用中的活动的类(如人物角色控制器类)
上面这些类就是控制器类 。不要将这些责任分配给 用户界面类 ;
MVC模式三层架构强调了控制模式的应用。
(1)系统事件的接收和处理通常由一个高级类来代替;
(2)一个子系统会有很多控制器类,分别处理不同的事务
注意:如果一个系统只设计一个控制器类并由一个view类来处理事务,显然不是好的设计,因为它违反了高内聚的原则。
2。6 Polymorphism 多态
当相关行为只是由于种类不同时,可以分配相关的责任给指定的种类。多态允许你设计出组件插入式的系统。
多态可以使设计的内聚程度提高
eg:绘画系统
shape(draw)--rectangle(draw)
--round(draw)
--ellipse(draw)
2.7 Pure Fabrication(纯虚构)
高内聚和低耦合使设计的目标,但是这二者又是向矛盾的。
高内聚意味着类的数量增多,对象间要合作完成任务,它们之间的连接就要增加,使得耦合度提高。解决这样矛盾的方法是使用 纯虚构模式。
我们设计一个高层次的类,用于分配高内聚的责任。
(抽象工厂模式)
eg:
winRectangle linuxRectangle
draw() draw()
|| ||
winShape linuxwinShape
draw() draw()
|| ||
==========================
||
entity
draw()
2.8 Indirection(间接)
直接耦合的两个子系统是错误的,会引起维护困难。
引入中间对象协调组件或服务的职责。
eg:
岗位Position 和 员工Employee
岗位和员工的关系,员工是分配在岗位上的,他们有连接
需要设计 一个中间类 分配Assignment,用于该连接。
好处:避免了两个子系统的直接相连
2。9 Protected Variations 受保护变化 也称 开闭原则 the open closed principle,ocp)
找出预计有变化或不稳定的点,我们有责任为这些变化的点创建稳定的接口.
一个软件实体应该对扩展开放,对修改关闭,应当使这个模块在不被修改的前提下可以扩展
eg:OpenGL Driect3D JDBC ODBC