熟悉GRASP并撰写心得

GRASP(General Responsibility Assignment Software Patterns),中文名称为“通用职责分配软件模式”,GRASP一共包括9种模式,如何决定一个系统有多少对象,每个对象都包括什么职责,GRASP模式给出了最基本的指导原则。初学者应该尽快掌握、理解这些原则,因为这是如何设计一个面向对象系统的基础。可以说,GRASP是学习使用设计模式的基础。

1、Infomation Expert(信息专家)
信息专家模式是面向设计的最基本原则,是我们平时使用最多,应该跟我们的思想融为一体的原则。也就是说,我们设计对象(类)的时候,如果某个类拥有完成某个职责所需要的所有信息,那么这个职责就应该分配给这个类来实现。这时,这个类就是相对于这个职责的信息专家。 
例如: 常见的网上商店的购物车(ShopCar),需要让每种商品(SKU)只在购物车内出现一次,购买相同商品,只需要更新商品的数量即可。如下图: 


针对这个问题需要权衡的是,比较商品是否相同的方法需要放到哪个类里来实现呢?分析业务得知需要根据商品的编号(SKUID)来唯一区分商品,而商品编号是唯一存在于商品类的,所以根据信息专家模式,应该把比较商品是否相同的方法放在商品类里。

2、Creator(创造者)
实际应用中,符合下列任一条件的时候,都应该由类 A 来创建类 B,这时 A 是 B 的创建者: 
a、A 是 B 的聚合 
b、A 是 B 的容器 
c、A 持有初始化 B 的信息(数据) 
d、A 记录 B 的实例 
e、A 频繁使用 B

如果一个类创建了另外一个类,那么这两个类之间就有了耦合,也可以说产生了依赖关系。依赖或耦合本身是没有错误的,但是他们带来的问题就是在以后的维护中产生连锁反应,而必要的耦合是逃不掉的,我们能做的就是正确的创建耦合关系,不要随便建立类之间的依赖关系,那么该如何去做呢?就是要遵守创建者模式规定的基本原则,凡是不符合以上条件的,都不能随便用 A 创建 B。

例如:因为订单(Order)是商品(SKU)的容器,所以应该由订单来创建商品。如下图: 


这里因为订单是商品的容器,也只有订单持有初始化商品的信息,所以这个耦合关系是正确的且没有办法避免的,所以由订单来创建商品。

3、Low coupling(低耦合)
低耦合模式的意思就是要我们尽可能地减少类之间的连接。

其作用非常重要:

a、低耦合降低了因一个类的变化而影响其他类的范围。

b、低耦合使用类更容易理解,因为类会变得简单,更内聚。

下面这些情况会造成类 A、B 之间的耦合:

a、A 是 B 的属性 
b、A 调用 B 的实例的方法 
c、A 的方法中引用的 B,例如 B 是 A 方法的返回值或参数。 
d、A 是 B 的子类,或者 A 实现 B

关于低耦合,还有下面一些基本原则:

a、Don’t Talk to Strangers 原则

意思就是说,不需要通信的两个对象之间,不要进行无谓的连接,连接了就有可能产生问题,不连接就一了百了了。

b、如果 A 已经和 B 有连接,如果分配 A 的职责给 B 不合适的话(违反信息专家模式),那么就把 B 的职责分配给 A。

c、两个不同模块的内部类之间不能连接,否则比招报应!

例如:Creator 模式的例子里,实际业务中需要另一个出货人来清点订单(Order)上的商品(SKU),并计算出商品的总价,但是由于订单和商品之间的耦合已经存在了,那么把这个职责分配给订单更合适,这样可以降低耦合,以便降低系统的复杂性。如下图: 


这里我们在订单类里增加了一个 TotalPrice() 方法来执行计算总价的职责,没有增加不必要的耦合

4、High cohesion(高内聚)
高内聚的意思是给类尽量分配内聚的职责,也可以说成是功能性内聚的职责。即功能性紧密相关的职责应该放在一个类里,并共同完成有限的功能,那么就是高内聚合。这样更有利于类的理解和重用,也便于类的维护。

高内聚也可以说是一种隔离,就像人体由很多独立的细胞组成,大厦由很多砖头、钢筋、混凝土组成,每一个部分(类)都有自己独立的职责和特性,每一个部分内部发生了问题,也不会影响其他部分,因为高内聚的对象之间是隔离开的。

例如:一个订单数据存取类(OrderDAO),订单即可以保存为 Excel 模式,也可以保存到数据库中;那么,不同的职责最好由不同的类来实现,这样才是高内聚的设计,如下图: 


这里我们把两种不同的数据存储功能分别放在了两个类里来实现,这样如果未来保存到 Excel 的功能发生错误,那么就去检查 OrderDAOExcel 类就可以了,这样也使系统更模块化,方便划分任务,比如这两个类就可以分配到不同的人同时进行开发,这样也提高了团队协作和开发进度。

设计模式如何解决设计问题
1 设计模式怎样解决设计问题
1.1 寻找合适的对象
面向对象设计最困难的部分是将系统分解为对象的集合。

设计的许多对象来源于现实世界的分析模型,这里和领域驱动设计有点关联。分析所得到的类,很多事现实中并不存在的类。这是抽象的结果。设计中的抽象对于产生灵活的设计至关重要。就像我设计的一个流程调度模型。

1.2 决定对象的粒度
记笔记可以让我达到沉流的状态。

1.3 指定对象接口
1.4 描述对象实现
OMT表示法:

1、 对象:最上面的黑体表示类名,下面依次是操作,数据。

2、 实例化:虚线箭头表示一个类实例化另外一个对象。

3、 继承:竖线和三角表示继承关系。

4、 抽象类:类名以黑体斜体表示,操作也用斜体表示。

5、 引用

箭头加黑点表示一个类引用另外一个类。

重点:

1、 类的继承和接口继承的比较

对象的类和对象的类型的区别:

对象的类定义了对象是怎样实现的,同时也定义了对象内部状态和操作的实现。对象的类型只与它的接口有关。一个对象可以由多个类型(支持多个接口),不同类的对象可以有相同的类型。

类和类型紧密相连,类定义了对象的操作,也定义了对象的类型。

类的继承和接口的继承的差别:

c++中接口继承接近于公有继承纯抽象类。纯实现继承或纯类继承接近于私有继承。

2、 对接口编程,而不是对实现编程——面向对象设计的第一个原则

1.5 运用复用机制
1、 继承和组合的比较

继承是一种白箱复用,父类的内部细节对子类可见。

对象组合彼此不知道对方内部细节,成为黑箱复用。

继承的优缺点:

1) 子类可以直接重定义父类的操作。

2) 编译时刻决定了,无法在运行期间更改。

3) 子类要知道父类的实现细节,这样就部分破坏了封装性。子类和父类依赖过于紧密,父类的某些变化必然导致子类的变化。开发过程中遇到过类似的问题。这种依赖,限制了灵活性以及复用性。比如,服务体系中经常出现这样的问题,导致代码拷贝。

组合(通过获得对象的引用而在运行时刻动态的定义)的优缺点:

1) 对象间通过接口彼此交互。

2) 对象只能通过接口访问,不要也不能知道对方细节,这样不会破坏封装性。

3) 运行时刻可以使用另外一个对象替换这个对象,提高了灵活性。

4) 对象的实现基于接口编写,所以实现上存在较少的依赖关系。

5) 优先使用组合有助于保持每个类被封装,并被集中在单个任务上,提高整体内聚性。类和类的层次都维持一个较小的规模,

6) 基于对象组合的设计会有更多的对象(而又较少的类),且系统的行为依赖于对象间的关系而不是定义在某个类的内部。

理想的情况下,应该通过组合原有构件实现新的功能,而不是创建新的构件。

面向对象设计的第二个原则:优先使用对象组合,而不是类继承。

2、 委托

委托时一种组合方法,它是组合具有与继承同样的能力。

委托的主要优点在于它便于在运行时刻组合对象操作,以及更改操作的组合方式。它是软件更加的灵活。

和其他的技术方案相同,它也存在不足之处:增加了软件的复杂度——动态的,高度参数化的软件比静态的软件更难于理解。

3、 继承和参数化类型的

1.6 关联运行时刻的结构和编译时刻的结构
1.7 设计应支持变化
设计应该支持变化——所说的是,一个设计方案,对变化要有一定的适应性,即封装变化。

变化是导致重新设计的原因。设计要对一定范围内的变化友好。

4、 对于程序的分层设计,对于处于同一分层的模块,对外应保持一定的抽象,并且,使用同种类型的通信协议。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值