java设计模式之装饰器模式

一、装饰器模式简介
装饰器模式可以动态给一个对象添加一些额外的职责,同时又不改变其结构。就象在墙上刷油漆.使用Decorator模式相比用生成子类方式达到功能的扩充显得更为灵活。这种模式创建了一个装饰类,用来包装原有的类,并在保持类方法签名完整性的前提下,提供了额外的功能。
装饰器模式的应用场景:
1、在不修改源代码的情况下,扩展一个类的功能。 
2、实现动态增加功能,动态撤销。


二、示例演示
1、业务需求:
假设现在需要一个汉堡,主体是鸡腿堡,我们可以选择添加生菜、酱、辣椒等等许多其他的配料,同时根据所加的配料情况,从新计算价格。这种情况下就可以使用装饰者模式。

2、首先定义一个公共接口:所有汉堡和配料都必须实现该接口。(事实上汉堡本身也可以看作鸡腿堡的一个配料)
public interface Condiment {           
    String getName();      
    double getPrice();   
}    


3、定义一个鸡腿堡的实现:(被装饰者的初始状态,有些自己的简单装饰)
public class ChickenBurger implements Condiment {    
    
    private String name;
    public ChickenBurger(){    //构造器
        name = "鸡腿堡";    
    }    
    public String getName(){
        return name;
    }
    public double getPrice() {    
        return 10;    //初始价格
    }    
    
}    


4、再定义各个配料的具体情况,这些配料就是装饰者。
首先定义生菜配料:
public class Lettuce implements Condiment {    
        
    Condiment humburger;//持有一个被装饰者(汉堡)的引用,这是实现装饰器模式的关键
        
    public Lettuce(Condiment humburger){ //用具体的汉堡实例来初始化
        this.humburger = humburger;    
    }    
    
    public String getName() {    
        return humburger.getName()+" 加生菜";    
    }    
 
    public double getPrice() {    
        return humburger.getPrice()+1.5;    
    }    
    
}    


在定义辣椒配料:
public class Chilli implements Condiment {    
        
    Condiment humburger;
        
    public Lettuce(Condiment humburger){ 
        this.humburger = humburger;    
    }    
    
    public String getName() {    
        return humburger.getName()+" 加辣椒";    
    }    
 
    public double getPrice() {    
        return humburger.getPrice();//辣椒免费供应    
    }    
    
} 




4、测试:
public class Test {    
    public static void main(String[] args) {    
        Condiment humburger = new ChickenBurger(); //初始化一个鸡腿汉堡实例   
        System.out.println(humburger.getName()+"  价钱:"+humburger.getPrice());   
        //测试单独加一种配料 
        Condiment lettuce = new Lettuce(humburger);    
        System.out.println(lettuce.getName()+"  价钱:"+lettuce.getPrice());    
        Condiment chilli = new Chilli(humburger);    
        System.out.println(chilli.getName()+"  价钱:"+chilli.getPrice());    


        //测试加多种配料
        humburger = new Lettuce(humburger); //加入生菜,然后返回装配好的实例
        humburger = new Chilli(humburger); //再加入辣椒,然后返回装配好的实例
        System.out.println(humburger.getName()+"  价钱:"+humburger.getPrice()); 
          
    }    
    
}    


三、总结
从上面的实现的方式发现这看起来像是一个对象一层一层包装起来一样,这也正是装饰模式别名“包装器”的由来。我的理解是这样的:
1、装饰模式的类Lettuce和Chilli其实是从公共接口类实现来的,也是用来装饰Condiment类的
2、同时在装饰类中有一个这样的构造方法:
public Lettuce(Condiment humburger){ 
        this.humburger = humburger;    
    }  
这个构造方法有点特殊的,参数是Condiment类型,利用多态特性,这个使得一层一层装饰成为了可能,也就是通过不断的给一个ChickenBurger对象增加功能变得极其方便;
3、还有一点就是体会一下在测试方法中具体使用。
humburger = new Lettuce(humburger); //加入生菜,然后返回装配好的实例
humburger = new Chilli(humburger); //再加入辣椒,然后返回装配好的实例
可以看出,我们每次用装饰后的对象去覆盖原对象,这样做的实现原理是利用了多态性。即无论Lettuce类对象还是Chilli类对象,都是一个Condiment的实例。


原文地址:https://www.cnblogs.com/kangsir/p/6653226.html