要给一个类添加属性或方法,除了直接在源文件中添加这种简陋的方法外,就是继承某个类或者与将其与某个类关联(作为内部属性等)起来,但如果要动态的添加,这两种方法都不合适,装饰者模式,应运而生。
先说装饰者模式的结构图
最上层的接口,是抽象的被装饰组件,里面只有抽象的方法,紧跟其下的两个类,左边是具体的被装饰组件,右边是抽象的被装饰者,最下层的两个类,是具体的装饰者,需要强调的是,装饰者是不需要知道被装饰者的存在的,也就是说,具体装饰者A、B和具体的被装饰者之间,没有任何的直接交互
这段话说的有点拗口,来一个简单的实例吧,假设我开了一家咖啡店,提供各种口味的咖啡,例如黑咖啡、卡布奇诺、拿铁等,每种咖啡都可以加方糖、奶精等等,那我怎样用代码实现价格计算,给每种咖啡定一个价格吗,黑咖啡原版、黑咖啡加糖版、黑咖啡加奶版、卡布奇诺原版、卡布奇诺加糖版……这显然不是一个聪明的做法,实际情况是怎么做的呢?黑咖啡、卡布奇诺、拿铁各有各的价,方糖、奶精也各有各的价,黑咖啡加方糖,或是其他什么组合,都只需要把两者的价格加起来就是了,这,就是装饰者模式,下面是这个例子的代码实现:
抽象的咖啡接口
public interface Coffee {
public int showPrice();
public String showTaste();
}
具体的某种咖啡类(黑咖啡)
public class BlackCoffee implements Coffee {
private int price = 10;
private String taste = "黑咖啡";
@Override
public int showPrice() {
// TODO Auto-generated method stub
return price;
}
@Override
public String showTaste() {
// TODO Auto-generated method stub
return taste;
}
}
抽象的咖啡伴侣类(方糖、奶精的父类)
public class Mate implements Coffee{
private Coffee coffee;
public Mate(Coffee coffee) {
this.coffee= coffee;
}
@Override
public int showPrice() {
return coffee.showPrice();
}
@Override
public String showTaste() {
return coffee.showTaste();
}
}
具体的咖啡伴侣
public class MilkDeco extends Mate{
public MilkDeco(Coffee coffee) {
super(coffee);
}
@Override
public int showPrice() {
// TODO Auto-generated method stub
return super.showPrice()+2;
}
@Override
public String showTaste() {
return super.showTaste()+"+牛奶";
}
}
package DecorateStyle2;
public class SugarDeco extends Mate{
public SugarDeco(Coffee coffee) {
super(coffee);
}
@Override
public int showPrice() {
return super.showPrice()+1;
}
@Override
public String showTaste() {
return super.showTaste()+"+糖";
}
}
测试类
public class Test {
public static void main(String[] args) {
Coffee coffee=new BlackCoffee();
SugarDeco sugar =new SugarDeco(coffee);
MilkDeco milk=new MilkDeco(sugar);
System.out.println(sugar.showTaste()+" "+sugar.showPrice());
System.out.println(milk.showTaste()+" "+milk.showPrice());
}
}
输出结果:
黑咖啡+糖 11
黑咖啡+糖+牛奶 13