本人JAVA新人一枚,最近偷闲学习《JAVA与模式》,在此做个笔记,喜欢的可以一起学习。
什么是装饰模式:
装饰模式又名包装模式,以客户端透明的方式扩展对象的功能,是继承关系的一种替代方案。
装饰模式的类图:
在装饰模式中有以下几种角色:
- 抽象构件(Component)角色:给出一个抽象接口,以规范准备接收附加责任的对象。
- 具体构件(Concrete Component)角色:定义一个将要接收附加责任的类。
- 装饰(Decorator)角色:持有一个构件(Component)对象的实例,并定义一个与抽象构件接口一致的接口。
- 具体装饰(Concrete Decorator)角色:负责给构件对象“贴上”附加的责任。
代码示例:
美猴王(孙猴子)有七十二般变化,但是无论孙猴子变化成什么,他本质上还是孙猴子,只是外表上加了一层装饰而已。此处就以此为例,写一个装饰模式的小demo。
首先是美猴王类(interface接口),即上述类图中的Component角色:
public interface MonkeyKing {
public void move();
}
然后是美猴王的本体,即具体构件(Concrete Component)角色,该类实现了MoneyKing接口:
public class TrueMonkeyKing implements MonkeyKing {
@Override
public void move() {
System.out.println("TrueMonkeyKing is moving.");
}
}
接下来是七十二变类,即装饰(Decorator)角色。请注意,七十二变不仅实现了MonkeyKing接口,并且持有一个MonkeyKing引用,而在实现move()方法时,实际上调用的是七十二变类所持有的MonkeyKing的move()方法,代码如下 :
public class SeventyTwoChanges implements MonkeyKing {
private MonkeyKing monkeyKing;
public SeventyTwoChanges(MonkeyKing mk){
this.monkeyKing = mk;
}
@Override
public void move() {
monkeyKing.move();
}
}
最后是具体装饰(Concrete Decorator)角色,变成老虎(ChangeToTiger),该类继承自七十二变类。代码如下:
public class ChangeToTiger extends SeventyTwoChanges {
public ChangeToTiger(MonkeyKing mk) {
super(mk);
}
public void move(){
System.out.println("the monkeyKing has changed to a tiger.");
System.out.println("tiger(monkeyKing) is moving.");
}
}
以下为测试代码:
public static void main(String[] args) {
MonkeyKing mk = new SeventyTwoChanges(
new ChangeToTiger(
new TrueMonkeyKing()));
mk.move();
}
执行结果为:
此例仅供理解参考,如有不对之处,请观者指正。
装饰模式的使用条件:
- 需要扩展一个类的功能,或给一个类附加责任。
- 需要动态地给一个对象增加功能,这些功能可以再动态地撤销。
- 需要增加由一些基本功能的排列组合而产生的非常大量的功能,从而使继承关系变得不现实。
装饰模式的优缺点:
使用装饰模式主要有以下的优点:
(1)装饰模式与继承关系的目的都是要扩展对象的功能,但是装饰模式可以提供比继承更多的灵活性。装饰模式允许系统动态地决定“贴上”一个需要的“装饰”,或者去除一个不需要的“装饰”。继承关系则不同,继承关系是静态的,它在系统运行前就决定了。
(2)通过使用不同的具体装饰类以及这些装饰类的排列组合,设计师可以创造出很多不同行为的组合。这一点也是继承难以做到的。
使用装饰模式的缺点:
虽然装饰模式比继承更加机动灵活,但同时也意味着装饰模式比继承更加容易出错。由于使用装饰模式,可以比继承关系需要更少数目的类,使得设计更易于进行。但在另一方面却使用了比继承关系更多的对象,一旦出错将难以排查。