設計模式學習筆記--裝飾者模式(Decorator Pattern)

概念

動態地將行爲附加到對象上。提供了比繼承更具有彈性的替代方案

所謂”動態”,是指在運行時根據具體的需求添加行爲,相對的,”靜態”則是在編譯時就確定了具體的行爲,兩者的區別很明顯,動態添加行爲具有很好的可擴展性,不需要修改已有的代碼,這對於維護更新是很有利的。

設計原則

  • 類應該對擴展開放,對修改關閉
    對原有代碼修改的代價是很大的,很可能引入未知的 bug 和意外的副作用,所以要對修改關閉,而使用擴展來應對改變的需求,在不修改原有代碼的情況下就能添加新行爲。

  • 多用組合,少用繼承
    如同策略模式,使用繼承設計子類的行爲,是在編譯時靜態決定的,而且所有的子類都會繼承到相同的行爲,而如果使用組合來擴展對象的行爲,就可以在運行時動態的添加行爲。

理解

在裝飾者模式中,存在兩個角色:組件(Component) 和 裝飾器(Decorator),並且兩者要實現相同的接口或抽象類(實現接口或繼承抽象類都行),這樣就可以使用裝飾器來裝飾組件了。現實生活中有很多這樣的例子,比如購買手機時,一個裸機就算是一個組件,如果想要裝飾下手機,加個手機套,貼個膜,送支手寫筆等,這些就是裝飾器。通過裝飾,在原有對象的基礎上得到了一個新的具有更多屬性和行爲的對象,比如加了手機套的手機比裸機耐摔,這便是裝飾後得到的新屬性;有了手寫筆的手機可以有新的輸入方式,這便是裝飾後得到的新行爲。

實例

現實生活中有很多事物可以描述裝飾者模式,就拿上面提到的手機配件的例子來寫一個模擬代碼

在這個例子中,有一個抽象類 Phones,作爲組件和裝飾器的共同基類;有兩個組件,AndroidPhone 和 iOSPhone,裝飾器數量不確定,因此有個裝飾器基類 PhoneAccessory,然後派生出一些可選的裝飾器,比如 手機殼:PhoneCover,手機膜:PhoneMembrane,手寫筆:PhonePen。他們之間的關係可以用如下類圖描述

這裏寫圖片描述

通過類圖可以很清楚的看到裝飾者模式的思路,下面是具體代碼:

抽象基類

public abstract class Phones {
    String description="nothing";

    public String getDescription(){
        return description;
    }
}

Android 手機

public class AndroidPhone extends Phones {

    public AndroidPhone(){
        description="Android 手機";
    }
}

iOS 手機

public class iOSPhone extends Phones {

    public iOSPhone(){
        description="iOS 手機";
    }
}

裝飾器基類

public abstract class PhoneAccessory extends Phones {

    public abstract String getDescription();

}

手機殼裝飾器

public class PhoneCover extends PhoneAccessory{
    private Phones phone;

    public PhoneCover(Phones p){
        this.phone=p;
    }

    @Override
    public String getDescription() {
        return this.phone.getDescription()+" 加了個保護套";
    }
}

手機膜裝飾器

public class PhoneMembrane extends PhoneAccessory {
    private Phones phones;

    public PhoneMembrane(Phones p){
        this.phones=p;
    }


    @Override
    public String getDescription() {
        return this.phones.getDescription()+" 貼了個膜";
    }
}

手寫筆裝飾器

public class PhonePen extends PhoneAccessory{
    private Phones phone;

    public PhonePen(Phones p){
        this.phone=p;
    }

    @Override
    public String getDescription() {
        return this.phone.getDescription()+" 送了支手寫筆";
    }
}

測試

public class MainTest {
    public static void main(String[] args) {
        Phones phone = new AndroidPhone();
        System.out.println(phone.getDescription());

        PhoneCover coverPhone = new PhoneCover(phone);
        System.out.println(coverPhone.getDescription());

        PhoneMembrane membranePhone = new PhoneMembrane(coverPhone);
        System.out.println(membranePhone.getDescription());

        PhonePen penPhone = new PhonePen(membranePhone);
        System.out.println(penPhone.getDescription());
    }
}

運行結果:

這裏寫圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章