参考: https://blog.youkuaiyun.com/lyabc123456/article/details/80089497
定义:动态地将责任附加到对象上。若要扩展功能,装饰者提供了比继承更有弹性的替代方案。
UML图:
装饰模式中的角色:
-
抽象构件(Component)角色:Component是一个抽象类或接口,是要包装的原始对象。
-
具体构件(ConcreteComponent)角色:是Component的实现类,最终要装饰的实际对象。
-
装饰(Decorator)角色:是一个抽象类,继承或实现了Component的接口,同时它持有一个对Component实例对象的引用,也可以有自己的方法。
-
具体装饰(ConcreteDecorator)角色:是Decorator的实现类,是具体的装饰者对象,负责给ConcreteComponent附加责任。
上面的是原理,不是很好理解。
举个栗子:抽象构件是饮料,具体构件是咖啡,装饰角色是加料,具体装饰是加糖,冰等等
再举个栗子:抽象构件是美女,具体构件是翠花,装饰角色是衣服,具体装饰是帽子、袜子等等
装饰者模式的精华在于给美女一件件穿衣服,下面是代码
抽象构件(Component)角色
public abstract class Coffee {
// 返回价格
public abstract int getPrice();
// 返回操作
public abstract String getName();
}
具体构件(ConcreteComponent)角色
public class SimpleCoffee extends Coffee{
@Override
public int getPrice() {
return 10;
}
@Override
public String getName() {
return "coffee:";
}
}
装饰(Decorator)角色---1
public class MilkDecorator extends Decorator {
public MilkDecorator(Coffee coffee) {
super(coffee);
}
@Override
public int getPrice() {
return coffee.getPrice()+10;
}
@Override
public String getName() {
return coffee.getName()+"+addMilk";
}
}
装饰(Decorator)角色---2
public class SugarDecorator extends Decorator {
public SugarDecorator(Coffee coffee) {
super(coffee);
}
@Override
public int getPrice() {
return coffee.getPrice() +10;
}
@Override
public String getName() {
return coffee.getName()+"+addSuger";
}
}
代码执行
public class Main {
public static void main(String[] args) {
//创建原始对象
Coffee coffee = new SimpleCoffee();
//第一次装饰
coffee = new MilkDecorator(coffee);
//第二次装饰
coffee = new SugarDecorator(coffee);
System.out.println(coffee.getPrice()+" "+coffee.getName());
}
}
执行结果
30 coffee:+addMilk+addSuger
执行效果:
其实核心代码就下面一行,在原来的价格加上加牛奶的价格,这就是装饰者的精髓
return coffee.getPrice() +10;
装饰者模式的优缺点:
优点:动态地为对象增加新的功能或者撤销功能(继承就不能做到这一点)
缺点:会产生过多的相似的对象,不容易拍错!
应用:Android的context,Java中的java.io包里面的InputStream类和OutputStream类