敏捷软件开发:原则模式与实践
单一职责原则:SRP (Single Responsible Principle)就一个类而言,应该仅有一个引起它变化的原因。对于违反SRP的情形,可考虑FACADE或者PROXY模式重构.
开放封闭原则:对于扩展是开放的,对于更改是封闭
获得封闭的办法:1使用抽象获得显式封闭 2使用数据驱动的方法获取封闭性
LiskOV替换原则:子类型必须能够替换掉他们的基类型.
DIP依赖倒置原则:
a高层模块不易不应该依赖于底层模块,二者都应该依赖于抽象
b抽象不应该依赖于细节,细节应该依赖于抽象
动态多态性与C++模板提供静态多态性:
ISP接口隔离原则:
使用委托分离接口
使用多重继承分离接口
薪水支付案例研究
Chapter 13 Command &Active Object模式
Active Object是Command的方式之一
主动对象模式
Active Object模式不属于《Design Pattern》23模式。实际上,她是一种特殊的Command Queue。其特殊之处在于:
1. 队列的拥有者会顺序地执行队列中所有Command对象的Execute方法。(这个其实不算特殊)
2.Command对象在自己的Execute方法结束前,可以把一个新的command对象(实际上常常是这个command对象自己)再加到队列的尾部。
看出来了吗,这个队列有可能不会终止的,他可以一直执行下去。这个可以作为一个应用或者服务的主模块了,想像一下她可以作多少事情吧。
《ASP》指出这个模式可以用来在一个线程中处理多任务的问题!!! ^_^ 太cool了。
如何处理呢?你可以把每个command对象看作是一个任务。他在Execute函数中,处理自己的任务,在任务告一段落时,记录自己的状态,然后把自己插入到队列的尾部,结束Execute方法。当队列轮完一周后,又会再次执行这个command对象的Execute方法。 ^_^ 很cool吧。
那么这种方法和多线程的方法相比有什么有缺点呢?
最大的优点是,所有的command都在同一个线程中,因此切换时,不需要进入内核模式!!超高效啊!!而且,可以有很多很多的command,数量上远远超过多线程的数量。
缺点嘛,是这种方法需要用户自己来实现调度,另外这其实是一种非剥夺模式的多任务,如果command处理不好,就会连累其它所有的command,因此实际上比多线程要更复杂。(嘿嘿,程序员能够怕麻烦吗?)
还有一点,Active Object运行于单线程,也就是说,她不能享受多处理器或多处理器核心带来的性能上的改善。
其实,这最后一点是非常致命的一点。也就是说,在当前intel的超线程CPU机器上,如果系统的负担并不重的时候。Active Object的效率有可能比多线程更低。
Anyway,这是一个非常有趣的模式。只是一般的程序员可能没有机会用到。但是请记住她,也许能有那么一次机会,可一用她来爽上一把。
Active Object模式就使得主动对象的每一个方法调用好像都是在并发环境中由工作线程来完成
可以通过ACE中这个模式的实现来理解,ACE中主动对象模式的参与者包括:
1 主动对象(ACE_Task)
2 调用队列(ACE_Activation_Queue)
3 主动对象的每一个方法对象的ACE_Method_Object
4 每一个方法对象的返回值处理对象ACE_Future
工作过程:
当调用主动对象的方法时,并不是直接调用主动对象的函数,
而是将主动对象方法的对应的ACE_Method_Object实例化并放入调用队列中,
并且返回一个ACE_Future对象。这个ACE_Method_Object对象会在执行线程中调用, 真正调用对应Active Object的方法,并将返回值结果信息保存在ACE_Future对象中 ,所以如果在结果会设置到ACE_Future对象中时,从中取结果则会阻塞。
Chapter 14 TEMPLATE method 和Strategy
Template Method 采用继承来解决问题
Strategy采用委托
Strategy比Template Method多了一个额外的好处:
尽管TEMPLATE METHOD模式允许一个 通用算法操纵多个可能的具体实现,但是Strategy完全遵守DIP原则,从而每个具体实现都可比被多个不同的通用算法操纵。
Chapter15 FAÇADE模式和MEDIATOR模式
FAÇADE:为一组复杂而且全面的接口对象提供一个简单且特定的接口时,可使用FAÇADE模式 明显且受限的方式
Mediator 隐藏且不受限的方式
Chapter16 SINGLETON模式和MONOSTATE模式
SINGLETON模式好处:
1跨平台:合适的中间件可把SINGLETON模式扩展为跨多个JVM
2适用于任何类
3可以通过派生创建
4延迟求值:如果SINGLETON从未使用过,那么就绝不会创建
代价
1摧毁方法未定义:没有好的方法去摧毁一个SINGLETON,或者解除其职责,即使添加一个decommission方法把instance置为NULL,系统中的其他模块仍然持有对该SINGLETON实例的引用。
2不能继承
3效率问题:每次调用Instance方法都会执行If语句,就大多数调用而言,IF多余
SINGLETON与MonoState模式区别:
SINGLETON关注行为,强制结构上的单一性,防止创建多个对象实例。使用私有构造函数,一个静态变量以及一个静态方法对实例化进行控制和限制
MonoState关注结构,强制行为上的单一性,没有强加结构方面的限制。简单的把对象的所有变量变成静态的。
MONOSTATE
好处:
透明性
可派生性
多态性
代价:
不可转换性:不能透过派生把常规类转换成MONOSTATE类
效率问题:MONOSTATE是真正的对象,所以会导致许多的创建和开销
内存占用:即使从未使用MONOSTATE,它的变量也要占据内存空间
平台局限性:不能跨多平台
MonoState模式:
先说说MonoState这个单词的意思,设计模式的名字都是很有意思的,因为为了方便交流、记忆,所以设计模式的命名都对该模式的意图进行了表述。Mono是一个词根,英语中Mono,Mon都表示的是1的意思,state意思为"状态"。MonoState的意思就是"单一的状态"。
MonoState模式同Singleton一样也是一种保证单一性的模式。但是它和Singleton模式有意图实现上的差别。Singleton模式是通过将默认构造函数声明为private限制客户端程序对类的直接new创建实例化,并使用static(类属)的方式来保证类的对象单一,而MonoState模式却是将它的构造函数声明为public,而将类中所有的字段声明为static(类属)。换句话说,MonoState并不限制创建对象的个数,但是它的状态却只有一个状态。
实例代码(Java):
public class MonoState ...{
private static String x;
public MonoState()...{}
public String GetX() ...{
return x;
}
public void SetX(String x) ...{
MonoState.x = x;
}
}
MonoState模式的实现很“诡异”啊!它关注的焦点是类所实例化的所有对象只具有惟一状态,而不管客户端程序实例化了多少个MonoState对象。
MonoState的好处是:
对客户端程序来说是透明的。客户端程序可以随意创建对象,但是对象的状态是唯一的,这一点客户端不用知道。
可继承性。从MonoState派生出来的也是MonoState。实际上,所有的MonoState的派生类都是相同的MonoState的一部分,因为它们都共享相同的static变量。
支持多态性。因为MonoState的方法不像Singleton的static方法,它是可以被重写的。
易于创建和销毁。
缺点:
不能转换。非MonoState类不能通过继承转换为MonoState类。
效率。因为它会有对象,所以有许多产生,销毁的过程。这些通常都导致效率降低。
3 空间占用。因为MonoState的变量都是静态的,所以尽管MonoState不被使用,它们同样要占用空间。
4 平台约束。不能够在不同的JVM实体或者不同的平台上使用MonoState。
Chapter17 NULL Object模式
NULLobject模式消除对NULL进行检查的需要,并且有助于简化代码。
Chapter23 Composite模式
Composite模式维护了一个含有多个实例的列表,当有方法被调用时,它就把这个方法委托给一个实例。
Chapter24 Observer模式
两种模型:
1拉模型
2推模型
(1) 主题需要为注册和注销通知提供一个接口。
(2) 下面的两点也需要满足:
A拉模型(In the pull model)--主题需要提供一个接口,可以使观察者查询主题获得需要的状态信息来更新自己的状态。
B推模型(In the push model)--主题发送观察者可能关注的状态信息。
(3) 观察者需要提供一个可以从主题接受通知的接口。
Observer模式最大的推动力来自开发封闭原则OCP,使用这个模式的动机是为了在增加新的观察对象是可以无需改动被观察的对象。
Chapter25 Abstract Server/Adapter/ Bridge
Adapter实现方法简单直接,它让所有的依赖关系都指向正确的方向,实现简单
Bridge模式稍稍复杂,在类型层次具有多个自由度的情况中,BRIGDE模式通常是有用的,可以把这些层次结构分开并通过桥把他们结合到一起。
开始不要使用直到明显可以看出完全分离策略和通信策略并且需要增加新的的连接策略时。才使用这些方法。
Chapter26 PROXY模式和STAIRWAY TO HEAVEN模式
Proxy模式好处:重要关系的分离(seperation of concerns),可以用来分离业务规则和任何种类的实现问题。
STAIRWAY TO HEAVEN 实现了对多重继承支持的语言
在真正需要PROXY模式或者STAIRWAYTOHEAVEN模式之前,预测对于他们的需要,开始时先使用FAÇADE模式,在必要时进行重构。
Chapter28 VISITOR模式
一般来说,如果一个应用程序中存在有需要以多种不同方式进行解释的数据结构,可使用 visitor模式
VISITOR模式允许再不更该县有类层次结构的情况下向其增加新的方法:
该系列模式如下:
VISITOR模式:核心机制是双重分发。两次分法形成了功能矩阵,一个轴是被访问的类型,一个轴是要执行的功能,非常适合不需要经常的增加新的派生类
ACYCLIC VISITOR模式:适用于访问层次结构非常不稳定,经常需要创建许多新类。
ACYCLIC模式创建了一个稀疏矩阵,访问者类不需要针对每一个被访问的派生类都实现visit函数。。ACYCLIC VISITOR模式允许我们忽略某些派生类和功能的组合。
DECORATOR模式
EXTENSION OBJECT模式:层次结构中的每个对象都持有一个特定扩展对象列表,同时每个对象也提供一个通过名字查找扩展对象的方法.
Chapter29 STATE模式
有限状态自动机FSM,提供了一个简单优雅的方法去揭示和定义复杂系统的行为。