《设计模式》
每一个模式描述了一个在我们周围不断重复发生的问题,以及该问题的解决方案的核心。这样,你就能一次又一次地使用该方案而不必做重复劳动
各个设计模式名称和功能简介
Abstract Factory( 3 . 1 ):提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。
A d a p t er ( 4 . 1 ):将一个类的接口转换成客户希望的另外一个接口。 A d a p t e r模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作。
B r i d g e( 4 . 2 ):将抽象部分与它的实现部分分离,使它们都可以独立地变化。
B u i l d e r( 3 . 2 ):将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。
Chain of Responsibility( 5 . 1 ):为解除请求的发送者和接收者之间耦合,而使多个对象都有机会处理这个请求。将这些对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理它。
C o m m a n d( 5 . 2 ):将一个请求封装为一个对象,从而使你可用不同的请求对客户进行参数化;对请求排队或记录请求日志,以及支持可取消的操作。
C o m p o s i t e( 4 . 3 ):将对象组合成树形结构以表示“部分 -整体”的层次结构。C o m p o s i t e使得客户对单个对象和复合对象的使用具有一致性。
D e c o r a t o r( 4 . 4 ):动态地给一个对象添加一些额外的职责。就扩展功能而言, D e c o r a t o r模式比生成子类方式更为灵活。
F a c a d e( 4 . 5 ):为子系统中的一组接口提供一个一致的界面, F a c a d e模式定义了一个高层接口,这个接口使得这一子系统更加容易使用。
Factory Method( 3 . 3 ):定义一个用于创建对象的接口,让子类决定将哪一个类实例化。
Factory Method使一个类的实例化延迟到其子类。
F l y w e i g h t( 4 . 6 ):运用共享技术有效地支持大量细粒度的对象。
I n t e r p r e t e r( 5 . 3 ):给定一个语言, 定义它的文法的一种表示,并定义一个解释器 , 该解释器使用该表示来解释语言中的句子。
I t e r a t o r( 5 . 4 ):提供一种方法顺序访问一个聚合对象中各个元素 , 而又不需暴露该对象的内部表示。
M e d i a t o r( 5 . 5 ):用一个中介对象来封装一系列的对象交互。中介者使各对象不需要显式地相互引用,从而使其耦合松散,而且可以独立地改变它们之间的交互。
M e m e n t o( 5 . 6 ):在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态。这样以后就可将该对象恢复到保存的状态。
O b s e r v e r( 5 . 7 ):定义对象间的一种一对多的依赖关系 ,以便当一个对象的状态发生改变时 ,所有依赖于它的对象都得到通知并自动刷新。
P r o t o t y p e( 3 . 4 ):用原型实例指定创建对象的种类,并且通过拷贝这个原型来创建新的对象。
P r o x y( 4 . 7 ):为其他对象提供一个代理以控制对这个对象的访问。
S i n g l e t o n( 3 . 5 ):保证一个类仅有一个实例,并提供一个访问它的全局访问点。
S t a t e( 5 . 8 ):允许一个对象在其内部状态改变时改变它的行为。对象看起来似乎修改了它所属的类。
S t r a t e g y (5 . 9 ):定义一系列的算法,把它们一个个封装起来, 并且使它们可相互替换。本模式使得算法的变化可独立于使用它的客户。
Template Method( 5 . 1 0 ):定义一个操作中的算法的骨架,而将一些步骤延迟到子类中。
Template Method使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。
Vi s i t o r( 5 . 11 ):表示一个作用于某对象结构中的各元素的操作。它使你可以在不改变各元素的类的前提下定义作用于这些元素的新操作。
多组合少继承:理想情况下,你不应为获得复用而去创建新的构件。你应该能够只使用对象组合技术,通过组装已有的构件就能获得你需要的功能。但是事实很少如此,因为可用构件的集合实际上并不足够丰富。使用继承的复用使得创建新的构件要比组装旧的构件来得容易。这样,继承和对象组合常一起使用。然而,我们的经验表明:设计者往往过度使用了继承这种复用技术。但依赖于对象组合技术的设计却有更好的复用性(或更简单)。你将会看到设计模式中一再使用对象组合技术
继承
先创建一个共性类(包括一些共同属性,共同方法)
再创建一个实体类继承共性类调用共性类方法(体现了多态性)
主函数调用实体类创建实体类对象,直接调用实体类方法
组合
先创建一个共性类(包括一些共同属性,共同方法)
创建实体类,用“构造函数”初始化实体类
主函数调用实体类先要创建共性类,再创建实体类,然后将共性类放到实体类中,最后调用实体类方法
继承:
//InheritTest.java 使用继承方式实现目标
class Animal{
private void beat(){
System.out.println("心脏跳动...");
}
public void breath(){
beat();
System.out.println("吸一口气,呼一口气,呼吸中...");
}
}
//继承Animal,直接复用父类的breath()方法
class Bird extends Animal{
//创建子类独有的方法fly()
public void fly(){
System.out.println("我是鸟,我在天空中自由的飞翔...");
}
}
//继承Animal,直接复用父类的breath()方法
class Wolf extends Animal{
//创建子类独有的方法run()
public void run(){
System.out.println("我是狼,我在草原上快速奔跑...");
}
}
public class InheritTest{
public static void main(String[] args){
//创建继承自Animal的Bird对象新实例b
Bird b=new Bird();
//新对象实例b可以breath()
b.breath();
//新对象实例b可以fly()
b.fly();
Wolf w=new Wolf();
w.breath();
w.run();
/*
---------- 运行Java程序 ----------
心脏跳动...
吸一口气,呼一口气,呼吸中...
我是鸟,我在天空中自由的飞翔...
心脏跳动...
吸一口气,呼一口气,呼吸中...
我是狼,我在草原上快速奔跑...
输出完毕 (耗时 0 秒) - 正常终止
*/
}
}
组合:
//CompositeTest.java 使用组合方式实现目标
class Animal{
private void beat(){
System.out.println("心脏跳动...");
}
public void breath(){
beat();
System.out.println("吸一口气,呼一口气,呼吸中...");
}
}
class Bird{
//定义一个Animal成员变量,以供组合之用
private Animal a;
//使用构造函数初始化成员变量
public Bird(Animal a){
this.a=a;
}
//通过调用成员变量的固有方法(a.breath())使新类具有相同的功能(breath())
public void breath(){
a.breath();
}
//为新类增加新的方法
public void fly(){
System.out.println("我是鸟,我在天空中自由的飞翔...");
}
}
class Wolf{
private Animal a;
public Wolf(Animal a){
this.a=a;
}
public void breath(){
a.breath();
}
public void run(){
System.out.println("我是狼,我在草原上快速奔跑...");
}
}
public class CompositeTest{
public static void main(String[] args){
//显式创建被组合的对象实例a1
Animal a1=new Animal();
//以a1为基础组合出新对象实例b
Bird b=new Bird(a1);
//新对象实例b可以breath()
b.breath();
//新对象实例b可以fly()
b.fly();
Animal a2=new Animal();
Wolf w=new Wolf(a2);
w.breath();
w.run();
/*
---------- 运行Java程序 ----------
心脏跳动...
吸一口气,呼一口气,呼吸中...
我是鸟,我在天空中自由的飞翔...
心脏跳动...
吸一口气,呼一口气,呼吸中...
我是狼,我在草原上快速奔跑...
输出完毕 (耗时 0 秒) - 正常终止
*/
}
}
如何使用设计模式?
1) 大致浏览一遍模式 特别注意其适用性部分和效果部分,确定它适合你的问题。
2 ) 回头研究结构部分、参与者部分和协作部分 确保你理解这个模式的类和对象以及它们是怎样关联的。
3 ) 看代码示例部分,看看这个模式代码形式的具体例子 研究代码将有助于你实现模式。
4 ) 选择模式参与者的名字,使它们在应用上下文中有意义 设计模式参与者的名字通常过于抽象而不会直接出现在应用中。然而,将参与者的名字和应用中出现的名字合并起来是很有用的。这会帮助你在实现中更显式的体现出模式来。例如,如果你在文本组合算法中使用了S t r a t e g y模式,那么你可能有名为S i m p l e L a y o u t S t r a t e g y或Te X L a y o u t S t r a t e g y这样的类。
5) 定义类 声明它们的接口,建立它们的继承关系,定义代表数据和对象引用的实例变量。识别模式会影响到的你的应用中存在的类,做出相应的修改。
6) 定义模式中专用于应用的操作名称 这里再一次体现出,名字一般依赖于应用。使用与每一个操作相关联的责任和协作作为指导。还有,你的名字约定要一致。例如,可以使用“C r e a t e - ”前缀统一标记F a c t o r y方法。
7) 实现执行模式中责任和协作的操作 实现部分提供线索指导你进行实现。代码示例部分的例子也能提供帮助。
设计模式不能够随意使用。通常你通过引入额外的间接层次获得灵活性和可变性的同时,你也使设计变得更复杂并 /或牺牲了一定的性能。一个设计模式只有当它提供的灵活性是真正需要的时候,才有必要使用。