1. 程式人生 > >Java設計模式——裝飾者模式

Java設計模式——裝飾者模式

應用場景:

一個人身高175cm,他覺得太矮泡不到妹子,穿了一雙加厚的襪子增加1cm,嗯感覺效果不明顯,再踩在一雙加厚1cm的鞋墊,最後還不滿意,再穿了一雙內建增高3cm的鞋子,成功地把自己的身高“提高”到180cm+,他就被裝飾成“大長腿”了。

什麼是裝飾者模式?

裝飾者模式簡單來說就是你想拓展A的功能,但是又不想把它拆了重建,這時你可以建立B,模仿(裝飾)A的所有功能,然後在某些方面上模仿(裝飾)得比A還要複雜,最後取而代之,以後要拓展B再建立C、D、E,一層套一層,理論上可以無限地巢狀。
在不需要修改原物件程式碼的基礎上建立新的物件(裝飾類),動態地把原物件包囊(巢狀),再拓展新的方法。

在學習I/O流時,可能很多新手會奇怪為什麼new DataInputStream(new InputStream),是因為使用了裝飾者模式
這裡寫圖片描述

類圖:
這裡寫圖片描述

MSN、ICQ為被裝飾類,talk()方法程式碼能進行普通文字聊天。
QQ、WeChat為裝飾類,talk()方法程式碼除了基本聊天還可以顯示使用者名稱稱和訊息傳送日期。以後還能建立新類,加上視訊聊天、語音通話。

裝飾者和被裝飾者繼承同一父類,所以裝飾者可以替代並且擴充套件父類的行為

這裡寫圖片描述

它們的功能不斷地在原基礎上加強。
talk()方法巢狀(遞迴)。

程式碼

public abstract class Contact {
    String name = "未知App"
; public abstract void talk(); public String getName() { return name; }; }
public abstract class Disguise extends Contact {
    Contact contact;

    public abstract String getName();
}
public class ICQ extends Contact {

    public ICQ(String name) {
        this.name = name;
    }

    @Override
public void talk() { System.out.println("一般聊天,噢噢噢"); } @Override public String getName() { return this.name; } }
public class QQ extends Disguise {

    public QQ(String name,Contact contact) {
        this.name = name;
        this.contact = contact;
    }

    @Override
    public String getName() {
        return   this.name + "裝飾了" + contact.getName();
    }

    @Override
    public void talk() {
         System.out.println(name + "  " + new Date().toString()); 
         contact.talk();
         System.out.println("裝飾後輸出");
    }
}
public static void main(String[] args) {
        Contact contact = new ICQ("ICQ");
        contact.talk();

        System.out.println("--------------分割線--------------");

        QQ qq = new QQ("QQ",contact);
        qq.talk();
}

輸出結果:
這裡寫圖片描述

值得一提的是裝飾類由於繼承了相同的父類,所以可以相互裝飾使用,正如Head First 裡所舉的例子:咖啡可以不停地放調料。

總結

裝飾者模式的優點是裝飾類可以巢狀的方式來達到功能擴充套件的目的。理論上可以無限巢狀,但是實際上,當裝飾若干次會發現,會產生許多的裝飾物件,程式因此變得複雜。