软件构造设计模式(上)
目录
软件构造设计模式(上)Strategy策略模式策略的抽象接口策略的具体实现需要采用策略的类客户端
Visitor访问者模式加入新方法Visitor接口Visitor接口的实现客户端
Observer观察者模式偶像类(被观察对象)粉丝的抽象接口(抽象观察者)粉丝的实现类(具体观察者)客户端
Template模版模式包含所有方法的抽象接口(抽象父类)具体类客户端
Decorator装饰器模式接口(抽象组件角色)实现类1(具体组件角色)实现类2(抽象装饰角色)实现类3(具体装饰角色)客户端
Adapter适配器模式原来的类新的适配的接口新的适配的类客户端
Strategy策略模式
指对象有某个行为,但在不同的场景中,该行为有不同的实现算法。定义一系列算法类,将每一个算法封装起来,并让它们可以相互替换。主要目的是将算法的定义和使用分开,也就是将算法的行为和环境分开,将算法的定义放在专门的策略类中,每一个策略类封装一个实现算法。 而使用算法的环境中针对抽象策略编程,而不是针对实现编程,符合依赖倒置原则。
策略的抽象接口
public interface Strategy{
public void function(参数
);
}
策略的具体实现
public class Method1 implements Strategy{
@Override
public void funcition(参数
){
......
}
}
需要采用策略的类
public class XX{
......
public void function(Strategy strategy
,参数
){
strategy
.function(参数
);
}
......
}
客户端
new XX().function(new Method1(),参数
);
其中function方法表示可以采取多种策略来实现的功能,相当于把这个功能具体的实现委派给了实现Strategy接口的类,也就是在Method1中写具体的代码,而原本的function方法只起到了delegation的作用。 对于没有实现策略模式的工程来说,Strategy和Method1是为了实现策略模式而新增的接口和类,function是已经实现的方法。在扩展为策略模式时,除了新增Strategy和Method1之外,还需要将function具体实现改为delegation,即将Strategy作为参数传入,而客户端调用的依然是function这个方法。
Visitor访问者模式
把结构和数据分开,编写一个访问者,去访问数据结构中的元素,然后把对各元素的处理全部交给访问者类。这样,当需要增加新的处理的时候,只需要编写新的访问者类,让数据结构可以接受访问者的访问即可。
加入新方法
public class XX{
public int accept
(Visitor visitor
){
visitor
.visit(this);
}
}
Visitor接口
public interface Visitor{
public int visit(XX x
);
public int visit(YY y
);
......
}
Visitor接口的实现
public class VisitorImpl implements Visitor{
......
}
客户端
Visitor visitor
= new VisitorImpl();
XX
.accept(visitor
);
反向delegation,直接将XX类作为参数传给visit方法,根据不同的类实现不同的visit。 要实现Visitor模式,除了添加Visitor接口和实现之外,在原有的类中加入accept方法来实现反向delegation,相当于把自己交给了Visitor,而客户端依然调用XX的accept方法。
Observer观察者模式
定义对象间的一种一对多的依赖关系,以便当一个对象的状态发生改变时,所以依赖于它的对象都得到通知并自动刷新。
偶像类(被观察对象)
public class Subject{
private List
<Observer> observers
= new ArrayList<Observer>();
private void notifyAllObservers(){
for(Observer observer
:observers
){
observer
.update();
}
}
public void attach(Observer observer
){
observers
.add(observer
);
}
}
粉丝的抽象接口(抽象观察者)
public abstract class Observer{
protected Subject subject
;
public abstract void update();
}
粉丝的实现类(具体观察者)
public class XXObserver extends Observer{
public XXObserver(Subject subject
){
this.subject
= subject
;
this.subject
.sttach(this);
}
@Override
public void update(){
System
.out
.println(“
...”
);
}
}
客户端
new XXObserver(subject
);
在这个模式中,偶像类在需要将改变通知给粉丝类时,要调用内部的notifyAllObservers方法,对粉丝遍历,调用它们的update方法,还要提供允许粉丝注册的attach方法;同时,粉丝类要在构造器中进行注册,还要有update()方法用来打印信息;而客户端只需new一个粉丝的实例,把偶像的实例作为参数传入即可。
Template模版模式
定义一个操作中算法的骨架,而将一些步骤延迟到子类中,模版方法使得子类可以不改变算法的结构即可重定义该算法的某些特定步骤。
包含所有方法的抽象接口(抽象父类)
public abstract class OrderProcessTemplate{
public abstract void XX();
public abstract void YY();
public final void ZZ(){
....
}
public final void processOrder(){
XX();
YY();
ZZ();
}
具体类
public class XXOrder extends OrderProcessTemplate{
@Override
...
}
客户端
OrderProcessTemplate order
=new XXOrder();
order
.processOrder();
模版模式,顾名思义,是指做事情的步骤一样,但具体的实现方法不同。因此,需要在抽象接口定义一个具体的类,内部按顺序调用各个方法;在这个抽象接口的具体类中override这些方法,来实现内部函数不同的目的;最后客户端只需要调用保存顺序的那个类即可。
Decorator装饰器模式
动态为对象添加功能。是一种替换继承关系的方案,无需通过继承增加子类就能扩展对象的新功能。使用对象的关联关系代替继承关系。
接口(抽象组件角色)
public interface Stack{...}
实现类1(具体组件角色)
public class Stack1 implements Stack{...}
实现类2(抽象装饰角色)
public abstract class Stack2 implements Stack{...}
实现类3(具体装饰角色)
public Stack3
extends Stack2 implements Stack{
private Stack stack
;
public Stack3(Stack stack
){
this.stack
= stack
;
}
......
}
客户端
new Stack3(Stack1 stack
);
如果要实现装饰器模式,Stack1作为已经存在的类,实现了Stack接口,Stack2和Stack3都是需要新添加的类,由于实现装饰的功能。还可以拓展新的类Stack4,Stack5等等,客户端只需:new Stack5(new Stack4(new Stack3(Stack1 stack)))。注:对于Stack1已经实现的功能,Stack3,4,5需要通过delegation来实现。
Adapter适配器模式
将一个类的接口转换成客户希望的另外一个接口,使得原本由于接口不兼容而不能一起工作的那些类能一起工作。适配器模式是一个比较简单的delegation,利用delegation,使得客户端能够使用原本参数不适配的方法。
原来的类
public class Old{
public void XX(int x1
,int x2
,int x3
,int x4
){
...
}
}
新的适配的接口
public interface New{
public void XX(int x1
,int x2
,int x3
,int x4
);
}
新的适配的类
public class New1 implements New{
public void XX(int x1
,int x2
,int x3
,int x4
){
new Old().XX(x1
-x2
,x2
-x3
,x3
-x4
,x4
);
}
}
客户端
New
xx = new New1();
xx
.XX(x1
,x2
,x3
,x4
);