装饰者模式:
装饰者模式对客户端透明的方式扩展对象的功能,是继承关系的一个替代方案。
结构
角色
抽象构件(Component)角色:给出一个抽象接口,以规范准备接受附加责任的对象。
具体构件(ConCreteComponent)角色:定义一个将要接受附加责任的类。
装饰(Decorator)角色:持有一个构件(Component)对象的实例,并定义一个与抽象构件接口一致的接口。
具体装饰(ConcreteDecorator)角色:负责给构件对象“贴上”附加的责任。
咖啡馆案例
有一个新开的咖啡馆,有很多种咖啡饮料,咖啡饮料种可以添加调料,调料也需要收费,需要设计一个订购咖啡的程序。
一种方式是建立一个饮料抽象类,然后每种调料组合都作为子类继承抽象类,这样会造成类爆炸,而且一种饮料或者调料的价格改变,多个类都要进行修改,不利于维护,不是一种好的方式。
使用装饰者模式可以比较好的解决这个问题
结构:
代码实现:
//Drink类
public abstract class Drink {
public String description="";
private float price=0f;
public void setDescription(String description)
{
this.description=description;
}
public String getDescription()
{
return description;
}
public float getPrice()
{
return price;
}
public void setPrice(float price)
{
this.price=price;
}
public abstract float cost();
}
//Coffee类
public class Coffee extends Drink {
@Override
public float cost() {
return getPrice();
}
}
public class Decaf extends Coffee {
public Decaf(){
setDescription("Decaf");
setPrice(5.0f);
}
}
//装饰者类
public class Decorator extends Drink {
private Drink Obj;
public Decorator(Drink Obj){
this.Obj=Obj;
};
@Override
public float cost() {
// TODO Auto-generated method stub
return getPrice()+Obj.cost();
}
}
//调料类
public class Milk extends Decorator {
public Milk(Drink Obj) {
super(Obj);
setDescription(Obj.description+"+milk");
setPrice(2.0f);
}
}
public class Chocolate extends Decorator {
public Chocolate(Drink Obj) {
super(Obj);
setDescription(Obj.description+"+Chocolate");
setPrice(3.0f);
}
}
//客户端使用
public class Client {
public static void main(String[] args) {
Drink decaf=new Decaf();
decaf.getDescription();
System.out.println(decaf.getDescription()+":"+decaf.cost());
Drink decaf1=new Decaf();
decaf1=new Chocolate(decaf1);
decaf1=new Milk(decaf1);
System.out.println(decaf1.getDescription()+":"+decaf1.cost());
}
}
结果:
客户端调用的过程类似于打包装,比如说要订一杯牛奶巧克力摩卡咖啡,可以先创建一杯单品对象摩卡咖啡,然后创建装饰者对象milk包装decaf,再创建装饰者对象chocolate包装milk与decaf。
计算费用的时候,先计算最外层Chocolate的费用,再一层一层叠加内部的费用,层层递进。
装饰者提供了比继承更有弹性的扩展方案,各种调料可以随意组合,需要添加新的调料时只需要新增一个类就可以了。JAVA中的IO流就用到了装饰者模式。