一 装饰者模式
装饰者模式:动态的将责任附加到对象身上。若要扩展,装饰者模式比继承更加有弹性。
装饰者模式秉承这一个开放,关闭原则。就是对扩展开放,对修改关闭,也就是说对该类可以做扩展,但是不可以修改该类的原始功能。
二 装饰者模式的示例
这里我们列举一个奶茶店的例子。起初,这个奶茶店只卖普通茶。代码示例如下:
先定义一个材料的接口:
public abstract class Material {
String desc;
public String getDesc(){
return desc;
}
public abstract float cost();
}
再定义一个普通的茶:
public class Tea extends Material{
public Tea(){
this.desc = "普通的茶";
}
@Override
public float cost() {
// TODO Auto-generated method stub
return 5.0f;
}
}
如果有顾客来买茶的话,那么只需要new 一个Tea对象即可,后来奶茶店扩张了,种类多样了,开始卖奶茶了,还有珍珠奶茶等多种茶,那么这个时候,我们是否需要去创建奶茶以及珍珠奶茶等多个对象呢?如果按照这个思路创建下去的话,那么将来有一百种奶茶,那么势必得创建一百个java类然后继承Material,如此下来,到时候种类继续扩展,多糖少糖,多奶少奶等情况,会创建java类都弄的开发人员头皮发麻。那么针对于这种情况,便可以用到装饰者模式。
首先奶茶的材料就是牛奶加上普通的茶,多奶的奶茶就是多加一份或者多份牛奶。那么我们就可以定义一个牛奶的原料对象,代码如下:
public class Milk extends Material{
private Material material;
public Milk(Material material){
this.material = material;
}
@Override
public String getDesc(){
return material.getDesc() + ", 牛奶";
}
@Override
public float cost() {
// TODO Auto-generated method stub
return 1.0f+material.cost();
}
}
如果需要珍珠奶茶的话,那么我们可以添加一个珍珠的原材料
public class Pearls extends Material{
private Material material;
public Pearls(Material material){
this.material = material;
}
@Override
public String getDesc(){
return material.getDesc() + ", 珍珠";
}
@Override
public float cost() {
// TODO Auto-generated method stub
return 1.5f + material.cost();
}
}
如果需要一份多奶的珍珠奶茶的话,代码如下:
public class Test {
public static void main(String[] args){
Material tea = new Tea();
tea = new Milk(tea);
tea = new Milk(tea);
tea = new Pearls(tea);
System.out.println(tea.getDesc() + "; 价格是: "+ tea.cost());
}
}
输出结果如下:
普通的茶, 牛奶, 牛奶, 珍珠; 价格是: 8.5
如果只需要一份奶茶的话,代码如下:
public class Test {
public static void main(String[] args){
Material tea = new Tea();
tea = new Milk(tea);
System.out.println(tea.getDesc() + "; 价格是: "+ tea.cost());
//tea = new Milk(tea);
//tea = new Pearls(tea);
}
}
//输出结果如下:
普通的茶, 牛奶; 价格是: 6.0
三 装饰者模式总结
由上述的案例我们可以理解,装饰者模式就是将牛奶,珍珠等原料加到普通的茶身上,从而得到奶茶,珍珠奶茶等多样的种类,而不是直接新增一个奶茶和珍珠奶茶的类。这种思想就是装饰者模式的思想。