基本介绍
装饰者模式:动态的将新功能附加到对象上。在对象功能扩展方面,它比继承更有弹性,装饰者模式也体现了开闭原则(ocp)
模式原理
- 装饰者模式就像打包一个快递
主体:比如:陶瓷、衣服 (Component) // 被装饰者
包装:比如:报纸填充、塑料泡沫、纸板、木板(Decorator) - Component 抽象主体,被装饰者,
- ConcreteComponent 具体的被装饰主体
- Decorator: 装饰者
在如图的 Component 与 ConcreteComponent 之间,如果 ConcreteComponent 类很多,还可以设计一个缓冲层,将共有的部分提取出来,抽象层一个类。
以星巴克咖啡订单为例运用装饰者模式
示例类图
示例代码
Component 抽象被修饰主体类
//饮品类
public abstract class Drink {
private String des;
private float price = 0.0f;
public String getDes() {
return des;
}
public void setDes(String des) {
this.des = des;
}
public float getPrice() {
return price;
}
public void setPrice(float price) {
this.price = price;
}
//计算费用的抽象方法
//子类来实现
public abstract float cost();
}
缓冲层咖啡类
//缓冲层咖啡类
public class Coffee extends Drink {
@Override
public float cost() {
return super.getPrice();
}
}
ConcreteComponent 具体被修饰主体类
//意大利咖啡类
public class Espresso extends Coffee {
public Espresso() {
setDes("意大利咖啡");
setPrice(6.0f);
}
}
//美式咖啡类
public class LongBlack extends Coffee {
public LongBlack() {
setDes("美国咖啡");
setPrice(5.0f);
}
}
装饰者
//佐料类
public class Decorator extends Drink {
private Drink obj;
public Decorator(Drink obj) {
this.obj = obj;
}
@Override
public float cost() {
return super.getPrice() + obj.cost();
}
@Override
public String getDes(){
//输出被装饰者的信息
return super.getDes() + ":" + super.getPrice() + " + " + obj.getDes();
}
}
具体装饰者
//牛奶佐料类
public class Milk extends Decorator {
public Milk(Drink obj) {
super(obj);
setDes("牛奶");
setPrice(2.0f);
}
}
//糖佐料类
public class Sugar extends Decorator {
public Sugar(Drink obj) {
super(obj);
setDes("糖");
setPrice(1.0f);
}
}
客户端使用
public class CoffeeBar {
public static void main(String[] args) {
//1、点一杯意大利咖啡
Drink order1 = new Espresso();
System.out.println(order1.getDes()+" = "+order1.cost());
//2、加奶
order1 = new Milk(order1);
System.out.println(order1.getDes()+" = "+order1.cost());
//3、加糖
order1 = new Sugar(order1);
System.out.println(order1.getDes()+" = "+order1.cost());
System.out.println("=========================================");
//1、点一杯美式咖啡
Drink order2 = new LongBlack();
System.out.println(order2.getDes()+" = "+order2.cost());
//2、加两份奶
order2 = new Milk(order2);
order2 = new Milk(order2);
System.out.println(order2.getDes()+" = "+order2.cost());
}
}
//输出结果
//意大利咖啡 = 6.0
//牛奶:2.0 + 意大利咖啡 = 8.0
//糖:1.0 + 牛奶:2.0 + 意大利咖啡 = 9.0
//=========================================
//美国咖啡 = 5.0
//牛奶:2.0 + 牛奶:2.0 + 美国咖啡 = 9.0
使用装饰者模式之后,对于增加被装饰者或者增加装饰者都极为方便,只需要增加对应的类,被装饰者继承被装饰者的抽象类,装饰者继承装饰着的父类。不用改动代码,直接就可以在用户端使用,非常巧妙。