設計模式學習1:裝飾者模式

設計模式學習1:裝飾者模式

最近在學習設計模式,在這篇博客中記錄下本身對裝飾者模式的理解。設計模式

1、定義

在不改變原有對象的基礎之上,將功能附加到對象上。提供了比繼承更有彈性的替代方案(擴展原有對象功能)ide

能夠看出裝飾者模式是用來擴展對象的功能的。學習

2、舉例說明

接下來我舉一個比較接地氣的例子來講明下裝飾者模式的應用:賣手抓餅,根據配料的不一樣(加雞蛋或者火腿),價格也不一樣。咱們的目的是建立一個體系,能夠隨着配料的增長可以適配價格的計算而不用修改原來的代碼。測試

1.建立一個手抓餅類,表明不帶任何配料的手抓餅

/**
 * 手抓餅父類
 * @author asus
 *
 */
public class ShouZhuaBing {
    private String description="手抓餅";
    
    public double price() {
        return 3;
    }
    
    public String getDescription() {
        return description;
    }
}

2.建立一個配料的父類(抽象裝飾者)

抽象的裝飾者要繼承手抓餅類ui

/**
 * 手抓餅配料的父類
 * @author asus
 *
 */
public abstract class PeiLiao extends ShouZhuaBing {
    //全部子類必須實現此方法
    public abstract double price();
    
    public abstract String getDescription();
}

3.建立具體的裝飾者

具體的裝飾者中持有一個被裝飾對象的引用,經過實現抽象裝飾者的方法來加強被裝飾對象的功能,在這個例子中就是把配料本身的價格累加到手抓餅自己的價格上。this

/**
 * 雞蛋類(一個裝飾者,用來裝飾手抓餅)
 * @author asus
 *
 */
public class JiDan extends PeiLiao {

    private ShouZhuaBing shouZhuaBing;
    private double myCost=1;
    
    public JiDan(ShouZhuaBing shouZhuaBing) {
        this.shouZhuaBing=shouZhuaBing;
    }
    
    @Override
    public double price() {
        //累加被裝飾對象的價格和裝飾者的價格
        return myCost+this.shouZhuaBing.price();
    }

    @Override
    public String getDescription() {
        return this.shouZhuaBing.getDescription()+"+雞蛋";
    }

}

4.測試

public class Client {
    public static void main(String[] args) {
        ShouZhuaBing shouZhuaBing1=new ShouZhuaBing();
        //單純一個餅的價格
        System.out.println(shouZhuaBing1.getDescription()+"-->"+shouZhuaBing1.price()+"元");
        
        //加雞蛋的餅價格,(用雞蛋去裝飾原來的手抓餅)
         shouZhuaBing1=new JiDan(shouZhuaBing1);
        System.out.println(shouZhuaBing1.getDescription()+"-->"+shouZhuaBing1.price()+"元");
    }
}

上面的代碼中,先用手抓餅父類計算了一個價格,再經過雞蛋裝飾類計算了加上配料的價格。設計

5.再增長一個配料類

/**
 * 火腿類(一個裝飾者,用來裝飾手抓餅)
 * @author asus
 *
 */
public class HuoTui extends PeiLiao {

    private ShouZhuaBing shouZhuaBing;
    private double myCost=2;
    
    public HuoTui(ShouZhuaBing shouZhuaBing) {
        this.shouZhuaBing=shouZhuaBing;
    }
    
    @Override
    public double price() {
        return myCost+this.shouZhuaBing.price();
    }

    @Override
    public String getDescription() {
        return this.shouZhuaBing.getDescription()+"+火腿";
    }

}

這時若是想計算加上兩種配料的價格,能夠繼續使用裝飾者修飾手抓餅類的對象code

public static void main(String[] args) {
        ShouZhuaBing shouZhuaBing1=new ShouZhuaBing();
        //單純一個餅的價格
        System.out.println(shouZhuaBing1.getDescription()+"-->"+shouZhuaBing1.price()+"元");
        
        //加雞蛋的餅價格,(用雞蛋去裝飾原來的手抓餅)
         shouZhuaBing1=new JiDan(shouZhuaBing1);
        System.out.println(shouZhuaBing1.getDescription()+"-->"+shouZhuaBing1.price()+"元");
        
        //再加火腿後的價格,(繼續用火腿類裝飾)
        shouZhuaBing1=new HuoTui(shouZhuaBing1);
        System.out.println(shouZhuaBing1.getDescription()+"-->"+shouZhuaBing1.price()+"元");
}

3、總結

經過以上的例子能夠發現,裝飾者模式中須要一個抽象裝飾者來約束具體裝飾者中的裝飾內容,而這個抽象裝飾者須要繼承被裝飾的對象。而後就能夠先建立一個被裝飾對象,再建立具體裝飾類的對象,把被裝飾對象做爲構造方法參數傳入。對象

相關文章
相關標籤/搜索