定义:
- 在不改变原有对象的基础之上, 将功能附加到对象上.
提供了比继承更有弹性的替代方案(扩展对象的功能)
类型:
- 结构型
使用场景
装饰器模式实现普通煎饼, 加鸡蛋, 加火腿, 加辣条等任意组合的煎饼.
如果不考虑设计模式, 使用常规方法实现, 那我需要设计很多类, 如普通煎饼, 鸡蛋煎饼, 火腿煎饼, 鸡蛋火腿煎饼等等各种煎饼类, 当装饰对象较多时, 类的数量是不可想象的所以绝不可取.
- 在这个例子中, 煎饼Battercake属于被装饰的对象, 火腿, 鸡蛋等属于装饰煎饼的装饰者Decorator, 经过火腿鸡蛋等装饰过的煎饼还是一个煎饼.
定义一个顶层抽象类, 煎饼与煎饼的装饰器都实现这个抽象IBattercake
public interface IBattercake {
/**
* 名称
* @return
*/
String getName();
/**
* 价格
*/
Integer getPrice();
}
煎饼
public class Battercake implements IBattercake{
private Integer price;
public Battercake(Integer price) {
this.price = price;
}
@Override
public String getName() {
return "煎饼";
}
@Override
public Integer getPrice() {
return price;
}
}
装饰器抽象类与实现类
public abstract class AbstractBattercakeDecorator implements IBattercake{
protected IBattercake battercake;
public AbstractBattercakeDecorator(IBattercake battercake) {
this.battercake = battercake;
}
}
public class EggBattercake extends AbstractBattercakeDecorator{
public EggBattercake(IBattercake battercake) {
super(battercake);
}
@Override
public String getName() {
return battercake.getName() + "加鸡蛋";
}
@Override
public Integer getPrice() {
return battercake.getPrice() + 1;
}
}
public class SausageBattercake extends AbstractBattercakeDecorator{
public SausageBattercake(IBattercake battercake) {
super(battercake);
}
@Override
public String getName() {
return battercake.getName() + "加火腿";
}
@Override
public Integer getPrice() {
return battercake.getPrice() + 2;
}
}
测试与输出
public class Test {
public static void main(String[] args) {
IBattercake battercake = new Battercake(5);
battercake = new EggBattercake(battercake);
System.out.println(battercake.getName() + ":" + battercake.getPrice());
battercake = new EggBattercake(battercake);
battercake = new SausageBattercake(battercake);
System.out.println(battercake.getName() + ":" + battercake.getPrice());
}
}
输出结果:
煎饼加鸡蛋:6
煎饼加鸡蛋加鸡蛋加火腿:9
uml图
TIM图片20190217150811.png
coding
源码中的应用
java.io.Reader 是一个经典的装饰器模式的应用, 如Reader, BufferReader, FileReader三个类BufferReader, FileReader都实现了Reader, 使用
Reader reader = new FileReader("filepath");
reader = new BufferedReader(reader);
得到了一个具有Buffer功能的FileReader,
类比煎饼的例子, Reader 相当于IBattercake,
FIleReader 相当于 Battercake被装饰者, BufferReader则是装饰对象 EggBattercake和SausageBattercake.
优点:
- 继承的有力补充, 比继承灵活, 不改变对象的情况下给一个对象扩展功能
- 通过不同装饰类实现不同的装饰效果
缺点:
- 出现更多的代码, 更多的类
网友评论