源代码
装饰者模式
装饰者模式可以在不改变现有对象结构的情况下,动态的给该对象增加一些职责(就是加一些额外的功能)。
结构
- 抽象构件类(Component):定义一个抽象类或接口来规范那个要加额外功能的对象。
- 具体构件类(ConcreteComponent):实现抽象构件,通过装饰角色为其添加一些职责。
- 抽象装饰类(Decorator):继承或实现抽象接口,并且包含具体构件的实例,可以通过其子类扩展具体构件的功能。
- 具体装饰类(ConcreteDecorator):实现抽象装饰类的具体方法,并给具体构件类添加职责。
案例
去快餐店点菜,我们可以点一个炒饭,然后加个蛋,加个牛肉。点一份炒饭就是具体构建类,加个蛋,加个牛肉就是额外添加的职责。
当然我们也可以使用继承的方式,让一个蛋炒饭继承炒饭,牛肉炒饭继承炒饭。但是这样的类或过多,而且扩展性不好。
类图如下,最关键的点就是ExtFood抽象类,他既继承了FastFood又引用了FastFood。
public class test {
public static void main(String[] args) {
Rice rice=new Rice();
System.out.println(rice.getName()+":" +rice.cost());
Egg egg=new Egg(rice);
System.out.println(egg.getName()+":" +egg.cost());
Beef beef=new Beef(egg);
System.out.println(beef.getName()+":" +beef.cost());
}
}
输出:
炒饭:10.0
炒饭加鸡蛋:11.0
炒饭加鸡蛋加牛肉:16.0
优点
- 装饰者模式可以带来比继承更加灵活的扩展功能,使用更加方便。可以通过组合不同的具体装饰类来获得又不同功能的多样化的结果。遵守了开闭原则。继承是静态的附加责任(写死的),装饰者是动态的附加责任。
- 具体装饰类和具体构件类可以互相独立扩展不会耦合。(可以添加火腿肠、炒面啥的)。装饰者模式可以动态扩展实现类的功能。
使用场景
- 当不能或不方便使用继承的方式对系统进行扩展时。
- 比如系统里面有大量独立的扩展,这样为了支持他们的组会就会有爆炸多的子类。
- final类
- 在不影响其他对象的情况下,以动态、透明的方式给单个对象添加职责。
- 对象的功能需要动态的添加和拆卸时。(鸡蛋卖完了,就把鸡蛋类删掉)
JDK中的案例
IO流中的包装类使用了装饰者模式。BufferedXXXXX
。
BufferedWriter
的类图,关键在右边的既继承又聚合。
和代理模式的区别
-
相同点
- 都要实现和目标类相同的目标对象。
- 都要在类里面声明目标对象。
- 都可以在不修改目标类的情况下扩展目标方法。
-
不同点
- 装饰者是为了增强目标对象,代理模式是为了保护和隐藏对象
- 装饰者中声明的目标对象是外界传进来的,代理模式的是在类里面创建的。