七、装饰模式
动态的给一个对象添加一些额外的职责,就增加功能来说,装饰模式比生成子类更为灵活。(与建造者模式不同,建造者模式要求建造过程必须是稳定的(按顺序),但是装饰模式完全可以不按照特定顺序,是一种组合)。
装饰模式以对客户透明的方式动态的给一个对象附加上更多的职责。客户端并不会感觉对象在装饰前和装饰后有什么不一样。装饰模式可以在不是用创建更多子类的情况下,将对象的功能加以扩展。
7.1装饰模式中的角色:
l 抽象构件(Component):给出一个抽象接口,一规范准备接受附加责任的对象。
l 具体构件(ConcreteComponent)角色:定义一个将要接受附加责任的类。
l 装饰(Decorator)角色:持有一个构件(Component)对象的实例,并且定义了一个与抽象构建接口一致的接口。
l 具体装饰(ConcreteDecorator)角色:负责给构件对象贴上附加责任。
//抽象构建角色(Component):
public interface Component{
//抽象方法子类必须继承,无{}
public void sample Operation();
}
//具体构件角色(ConcreteComponent):
publicclass ConcreteComponent implements Component{
@override
public void sampleOperation(){
//书写相关代码
}
}
//装饰角色(ConcreteDecorator):
publicclass Decorator implements Component{
private Component component;
public Decoratortor(Component component){
This.component=componennt;
}
@override
public void sampleOperation();
}
//具体装饰角色:
publicclass ConcreteDecoratorA extends Decorator{
public ConcreteDecoretorA(Componentcomponent){
Super(componennt);
}
@override
public void sampleOperation(){
Super.sampleOperation();
//写相关代码
}
}
publicclass ConcreteDecoratorB extends Decorator{
public ConcreteDecoretorBComponentcomponent){
Super(componennt);
}
@override
public void sampleOperation(){
super.sampleOperation();
//写相关代码
}
}
7.2优点:
l 把类中的装饰功能从类中版以去除,这样可以简化原有的类,有效的吧类的核心职责和装饰功能区分开来,而且可以去除相关类的重复装饰逻辑。
l 装饰模式与继承关系的目的都是要扩展对象的功能,但是装饰模式可以提供比继承更多的灵活性。装饰模式允许系统动态的君顶贴上一个需要的装饰,或者踢掉有个不需要的装饰。继承关系则不同,继承关系是静态的,他在系统运行前就决定了。
l 通过使用不同的具体装饰类以及这些装饰类的排列组合,设计师可以创造出很多不同行为的组合。
7.4缺点:
l 由于使用装饰模式,可以比使用继承关系需要较少数目的类。使用较小的类,当然设计类比较容易进行。但是另一方面,用于装饰模式会产生比继承关系更多的对象。更多的对象会使得查错变得困难,特别是这些对象看上去很像。
应用:装饰模式在java语言中的应用最著名的应用莫过于java I/O标准库的设计了。
7.5 例子:齐天大圣七十二变:
孙悟空有七十二般变化,他的每一种变化都给他带来一种附加的本领。他变成鱼儿时,就可以到水里游泳;他变成鸟儿时,就可以在天上飞行。
本例中,Component的角色便由鼎鼎大名的齐天大圣扮演;ConcreteComponent的角色属于大圣的本尊,就是猢狲本人;Decorator的角色由大圣的七十二变扮演。而ConcreteDecorator的角色便是鱼儿、鸟儿等七十二般变化。
源代码:
抽象构件角色“齐天大圣”接口定义了一个move()方法,这是所有的具体构件类和装饰类必须实现的。//抽象方法子类必须继承,无{}
//大圣的尊号
public interface TheGreatestSage {
public voidmove();
}
// 具体构件角色“大圣本尊”猢狲类
//复制代码
public class Monkey implements TheGreatestSage {
@Override
public void move(){
//代码
System.out.println("Monkey Move");
}
}
复制代码
抽象装饰角色“七十二变”
复制代码
public class Change implements TheGreatestSage {
privateTheGreatestSage sage;
publicChange(TheGreatestSage sage){
this.sage =sage;
}
@Override
public void move(){
// 代码
sage.move();
}
}
复制代码
具体装饰角色“鱼儿”
复制代码
public class Fish extends Change {
publicFish(TheGreatestSage sage) {
super(sage);
}
@Override
public void move(){
// 代码
System.out.println("Fish Move");
}
}
复制代码
具体装饰角色“鸟儿”
复制代码
public class Bird extends Change {
publicBird(TheGreatestSage sage) {
super(sage);
}
@Override
public void move(){
// 代码
System.out.println("Bird Move");
}
}
复制代码
客户端类
复制代码
public class Client {
public static voidmain(String[] args) {
TheGreatestSage sage = new Monkey();
// 第一种写法
TheGreatestSage bird = new Bird(sage);
TheGreatestSage fish = new Fish(bird);
// 第二种写法
//TheGreatestSage fish = new Fish(new Bird(sage));
fish.move();
}
}
复制代码
“大圣本尊”是ConcreteComponent类,而“鸟儿”、“鱼儿”是装饰类。要装饰的是“大圣本尊”,也即“猢狲”实例。
上面的例子中,系统把大圣从一只猢狲装饰成了一只鸟儿(把鸟儿的功能加到了猢狲身上),然后又把鸟儿装饰成了一条鱼儿(把鱼儿的功能加到了猢狲+鸟儿身上,得到了猢狲+鸟儿+鱼儿)。 “大圣本尊”是ConcreteComponent类,而“鸟儿”、“鱼儿”是装饰类。要装饰的是“大圣本尊”,也即“猢狲”实例。
上面的例子中,系统把大圣从一只猢狲装饰成了一只鸟儿(把鸟儿的功能加到了猢狲身上),然后又把鸟儿装饰成了一条鱼儿(把鱼儿的功能加到了猢狲+鸟儿身上,得到了猢狲+鸟儿+鱼儿)。
8、Memento(备忘录模式)
备忘录模式又叫做快照模式(Snapshot Pattern)或Token模式,是对象的行为模式。
备忘录对象是一个用来存储另外一个对象内部状态的快照的对象。备忘录模式的用意是在不破坏封装的条件下,将一个对象的状态捕捉(Capture)住,并外部化,存储起来,从而可以在将来合适的时候把这个对象还原到存储起来的状态。备忘录模式常常与命令模式和迭代子模式一同使用。
备忘录模式所涉及的角色有三个:
① Originator(发起人): 负责创建一个备忘录Memento,用以记录当前时刻它的内部状态,并可使用备忘录恢复内部状态。Originator可根据需要决定Memento存储Originator的哪些内部状态。
② Memento(备忘录): 负责存储Originnator对象的内部状态,并可防止Originator以外的其他对象访问备忘录Memento,备忘录有两个接口,Caretaker只能看到备忘录的窄接口,它只能将备忘录传递给其他对象。
③、 Caretaker(管理者):负责保存好备忘录Memento,不能对备忘录的内容进行操作或检查。
//发起者
Public classOriginator {
privateString state;
/**
* 工厂方法,返回一个新的备忘录对象
*/
public Memento createMemento(){
return new Memento(state);
}
/**
* 将发起人恢复到备忘录对象所记载的状态
*/
public void restoreMemento(Mementomemento){
this.state =memento.getState();
}
public String getState() {
returnstate;
}
public void setState(Stringstate) {
this.state = state;
System.out.println("当前状态:"+ this.state);
}
}
//备忘录
public classMemento {
private String state;
public Memento(String state){
this.state = state;
}
public String getState() {
returnstate;
}
publicvoidsetState(String state) {
this.state = state;
}
}
//管理者:
public classCaretaker {
private Memento memento;
/**
* 备忘录的取值方法
*/
public Memento retrieveMemento(){
return this.memento;
}
/**
* 备忘录的赋值方法
*/
public void saveMemento(Mementomemento){
this.memento = memento;
}
}
使用:
//发起人
Originator o = new Originator();
//管理者
Caretaker c = new Caretaker();
//改变负责人对象的状态
o.setState("On");
//创建备忘录对象,并将发起人对象的状态储存起来
c.saveMemento(o.createMemento());
//修改发起人的状态
o.setState("Off");
//恢复发起人对象的状态
o.restoreMemento(c.retrieveMemento());