什么是装饰者模式
定义
装饰模式是以对客户端透明的方式扩展对象的功能,是继承关系的一个替代方案。
作用
动态为一个对象增加新的功能。
装饰模式是一种用于代替继承的技术,无须通过继承增加子类就能扩展对象的新功能。使用对象的关联关系代替继承关系,更加灵活,同时避免类型体系的快速膨胀。
模式结构
Component: 为接口/抽象类,用于使真实对象和装饰类有共同的接口,这样客户端才能使用装饰类对真实对象进行装饰。
ConcreteComponent: 为真实对象实现类,有真实对象的具体实现方法。
Decorator : 为装饰抽象/接口类,装饰对象接受所有客户端的请求,并把这些请求转发给真实的对象。这样,就能在真实对象调用前后增加新的功能。
ConcreteDecorate具体装饰角色:负责给构件对象增加新的功能。
装饰者模式的具体实现
下面我们用一个咖啡模拟售卖来体现装饰者模式的具体实现
首先创建一台只卖蓝山咖啡的售卖机:
抽象售卖机类:
public abstract class Decorater {
public abstract void sell();
}
售卖机实现类:
public class Dec extends Decorater{
private String coffee="蓝山";
public void sell() {
System.out.println(coffee);
}
}
如果我们想售卖更多的品种,比如说添加摩卡、美式等。如果不用装饰者模式,我们就需要添加一个摩卡类,一个美式类。然后客户需要哪个咖啡时在客户端分别调用该类。
但是如果我们用装饰者模式,我们可以这样实现:
先创建一个装饰抽象类:
public abstract class Add extends Decorater{
public abstract void sell();
}
再具体实现装饰(添加美式、摩卡):
public class Add1 extends Add{
private String coffee="美式";
private Decorater dec;
public Add1(Decorater dec) {
this.dec=dec;
}
public void sell() {
dec.sell();
System.out.println(coffee);
}
}
public class Add2 extends Add{
private String coffee="摩卡";
private Decorater dec;
public Add2(Decorater dec) {
this.dec=dec;
}
public void sell() {
dec.sell();
System.out.println(coffee);
}
}
客户端(使售卖机添加售卖摩卡、美式的功能):
public class Client {
public static void main(String[] args) {
// TODO Auto-generated method stub
Decorater coffee=new Dec();
coffee.sell();
//用装饰者模式添加功能
Decorater coff=new Add1(coffee);
coff.sell();
Decorater co=new Add2(coff);
co.sell();
}
}
输出:
蓝山
蓝山
美式
蓝山
美式
摩卡
总结
用装饰者模式可以降低系统的耦合度,可以动态的增加或删除对象的责任,并使得需要装饰的具体构建类和具体装饰类可以独立变化,以便增加新的具体构建类和具体装饰类。
优点:
扩展对象功能,比继承灵活,不会导致类个数急剧增加。
可以对一个对象进行多次装饰,创造出不同行为的组合,得到功能更加强大的对象。
具体构 件 类和具体装饰类可以独立变化,用户可以根据需要自己增加新的 具体构件子类和具体装饰子类。
缺点:
产生很多小对象。大量小的对象占据内存,一定程度上影响性能。
装饰模式易出错,调试排查比较麻烦。