装饰器模式(Decorator Pattern)
- 装饰器模式:动态的将新功能附加在对象上,在对象扩展方面,它比继承更有弹性,也体现了开闭原则。
- 这种类型属于结构型设计模式。
装饰器模式包含一下几个核心角色:
- 抽象组件(Component):定义了原始对象和装饰器对象的公共接口或抽象类,可以是具体组件类的父类或接口。
- 具体组件(Concrete Component):是被装饰的原始对象,它定义了需要添加新功能的对象。
- 抽象装饰器(Decorator):继承自抽象组件,它包含了一个抽象组件对象,并定义了与抽象组件相同的接口,同时可以通过组合方式持有其他装饰器对象。
- 具体装饰器(Concrete Decorator):实现了抽象装饰器的接口,负责向抽象组件添加新的功能。具体装饰器通常会在调用原始对象的方法之前或之后执行自己的操作。
引入问题
1.1 一个咖啡订单项目:
- 咖啡的品种:Espresso(意大利咖啡)、ShortBlack(浓缩咖啡)、LongBlack(美式咖啡)、Decaf(无因咖啡)
- 调料:Milk(牛奶)、Soy(豆浆)、Choclate(巧克力)
- 要求在扩展新的咖啡种类时,具有良好的扩展性,改动方便,维护方便。
- 计算不同种类咖啡的费用,可以单点咖啡,也可以单点咖啡+调料组合。
1.2装饰器类图分析:
类图说明:
- Drink 是抽象类,相当于Component。
- ShortBlack 就是单品咖啡。
- Decorator是一个装饰类,含有一个被装饰的对象Drink
- Decorator的cost方法进行一个费用的叠加计算,递归的计算价格
1.3代码实现:
public abstract class Drink {
public 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();
}
}
public class Decirator extends Drink{
private Drink obj;
public Decirator(Drink drink){
this.obj = drink;
}
@Override
public String getDes() {
return super.getDes();
}
@Override
public float cost() {
return super.getPrice() + obj.cost();
}
}
public class Milk extends Decirator {
public Milk(Drink drink) {
super(drink);
setDes(drink.getDes() + "牛奶");
setPrice(2.0f);
}
}
public class Soy extends Decirator{
public Soy(Drink drink) {
super(drink);
setDes("豆浆");
setPrice(1.5f);
}
}
public class Espresso extends Coffee {
public Espresso(){
setDes("意大利咖啡");
setPrice(6.0f);
}
}
public class LongBlack extends Coffee{
public LongBlack(){
setDes("黑咖啡");
setPrice(5.0f);
}
}
public static void main(String[] args) {
Drink drink = new LongBlack();
drink = new Milk(drink);
System.out.println(drink.cost());
System.out.println(drink.getDes());
}
装饰器模式的注意事项
- 优点:装饰类和被装饰类可以独立发展,不回相互耦合,装饰模式是继承的一个替代模式,装饰模式可以动态扩展一个实现类的功能。
- 可以代替继承。
- 缺点:多层的装饰类会比较复杂。