第七色在线视频,2021少妇久久久久久久久久,亚洲欧洲精品成人久久av18,亚洲国产精品特色大片观看完整版,孙宇晨将参加特朗普的晚宴

全部開(kāi)發(fā)者教程

裝飾者模式

每天我們出門(mén)前,一定都會(huì)選擇今天上衣穿什么,褲子穿什么,搭配什么鞋子,大衣穿什么。最后一定是做好選擇,打扮好才會(huì)出門(mén)。這個(gè)過(guò)程其實(shí)就是裝飾者模要做的事情 ---- 對(duì)一個(gè)對(duì)象增加額外的功能。

我們?cè)倏匆粋€(gè)例子。我們都吃過(guò)煎餅,除了面餅之外,我們還要加雞蛋、加蔥花、香菜、面醬、辣醬。現(xiàn)在還有新花樣,加辣條、加雞柳。一切都始于一張面餅,攤煎餅的過(guò)程就是在不斷對(duì)這張面餅添加新特性。
圖片描述

我們通過(guò)繼承也可以為對(duì)象增加功能,比如我們有個(gè)煎餅的父類(lèi),默認(rèn)已經(jīng)有面餅、面醬、雞蛋啊。那么我們可以派生出 全都放的普通煎餅、不辣的普通煎餅、不辣不放香菜的普通煎餅、不辣不放蔥的普通煎餅、全都放的辣條煎餅、全都放的雞柳煎餅…… 這只是很小一部分。通過(guò)繼承的話,由于情況太多,會(huì)造成對(duì)象爆炸。

那我們還可以通過(guò)組合的方式來(lái)擴(kuò)展類(lèi)啊,比如煎餅對(duì)象中,我們可以設(shè)置不同屬性,比如是否有蔥、是否有香菜、是否有辣條、是否有雞柳等等。這樣看起來(lái)也能很好的解決攤煎餅的問(wèn)題。但如果想要加腸、加油條怎么辦?想要加兩個(gè)雞蛋怎么辦?我們只能修改煎餅對(duì)象。這就違反了開(kāi)閉原則。顯然這樣也是不夠靈活的。

裝飾者模式能夠很好的解決對(duì)象的動(dòng)態(tài)擴(kuò)展,不管你想穿什么,都可以隨便搭配。不過(guò)這個(gè)煎餅要怎么做,也都能隨意的擴(kuò)展支持,而不需要改已有的代碼。接下來(lái)我們就來(lái)看看如何通過(guò)裝飾者模式來(lái)攤煎餅的。

1. 實(shí)現(xiàn)裝飾者模式

對(duì)于攤煎餅來(lái)說(shuō),我們都是對(duì)于一個(gè)基礎(chǔ)的煎餅對(duì)象做裝飾,比如我想要一套兩個(gè)雞蛋、有辣椒、蔥、辣條的煎餅,那么我只需要先聲明一個(gè)基本的煎餅對(duì)象,然后用加雞蛋裝飾類(lèi)裝飾它,然后再用加辣醬裝飾類(lèi)裝飾它,再用加蔥的裝飾類(lèi)裝飾它,最后再用加辣條的裝飾類(lèi)裝飾它。最終就得到了我想要的煎餅。不過(guò)請(qǐng)注意,不管你怎么裝飾,最終得到的還是煎餅,并不是其他東西。

裝飾者模式的核心思想是對(duì)已有的對(duì)象,一層一層的用裝飾類(lèi)去裝飾它,擴(kuò)展它的特性。這樣做可以更為動(dòng)態(tài)的為對(duì)象增加功能。我們看看代碼如何實(shí)現(xiàn):

先定義煎餅接口:

public interface Pancake {
    void cook();
}

接口里只定義了一個(gè)制作方法。

煎餅接口的實(shí)現(xiàn)類(lèi):

public class BasicPancake implements Pancake {
    @Override
    public void cook() {
        System.out.println("加一勺面");
        System.out.println("加一個(gè)雞蛋");
    }
}

作為一個(gè)最基本的煎餅,總得有面,有雞蛋吧。其他的材料留給裝飾類(lèi)來(lái)實(shí)現(xiàn)。

接下來(lái)我們定義裝飾抽象類(lèi):

public abstract class PancakeDecorator implements Pancake {
    protected Pancake pancake;

    public void setPancake(Pancake pancake) {
        this.pancake = pancake;
    }

    public void cook() {
        if (pancake != null) {
            pancake.cook();
        }
    }
}

可以看到 PancakeDecorator 同樣要實(shí)現(xiàn) Pancke 接口。并且持有 Pancke 類(lèi)型的引用,自己實(shí)現(xiàn)的 cook 方法實(shí)際調(diào)用了持有的 Pancake 對(duì)象的 cook 方法。

加辣醬的裝飾類(lèi)代碼如下,其他裝飾實(shí)現(xiàn)類(lèi)是類(lèi)似的。

public class AddSpicyDecorator extends PancakeDecorator{
    @Override
    public void cook(){
        super.cook();
        System.out.println("加辣醬");
    }
}

cook 方法首先調(diào)父類(lèi)的 cook 方法,然后再加入自己的特性。

客戶端代碼如下,我們看看如何利用裝飾類(lèi)來(lái)生成你想要的煎餅。

public class Client {
    public static void main(String[] args) {
        Pancake pancake = new BasicPancake();
        PancakeDecorator addEggPancake = new AddEggDecorator();
        addEggPancake.setPancake(pancake);

        PancakeDecorator addSaucePancake = new AddSauceDecorator();
        addSaucePancake.setPancake(addEggPancake);

        PancakeDecorator addLaTiaoPancake = new AddLaTiaoDecorator();
        addLaTiaoPancake.setPancake(addSaucePancake);

        addLaTiaoPancake.cook();
    }
}

我們聲明了三個(gè)包裝類(lèi),對(duì) BasicPancake 層層包裝,最后得到一套兩個(gè)雞蛋、加辣醬、加辣條的煎餅。運(yùn)行后輸出如下:

加一勺面
加一個(gè)雞蛋
加一個(gè)雞蛋
加面醬
加辣條

如果你研發(fā)了新煎餅,要加新的輔料,比如香腸、榨菜之類(lèi),那么只需要增加裝飾類(lèi)的實(shí)現(xiàn)即可。從而實(shí)現(xiàn)了開(kāi)閉原則。

類(lèi)圖如下:
圖片描述

2. 裝飾者模式優(yōu)缺點(diǎn)

2.1 優(yōu)點(diǎn)

  1. 動(dòng)態(tài)的為對(duì)象添加額外職責(zé):通過(guò)組合不同裝飾類(lèi),非常靈活的為對(duì)象增加額外的職責(zé);
  2. 避免子類(lèi)爆炸:當(dāng)不同的特性組合,構(gòu)成不同的子類(lèi)時(shí),必然造成子類(lèi)爆炸。但通過(guò)裝飾者靈活組合,可以避免這個(gè)問(wèn);
  3. 分離核心功能和裝飾功能:核心業(yè)務(wù)保留在 Component 的子類(lèi)中。而裝飾特性在 Decorator 的實(shí)現(xiàn)類(lèi)中去實(shí)現(xiàn)。面對(duì)裝飾特性的變化,實(shí)現(xiàn)了開(kāi)閉原則,只需要增加裝飾實(shí)現(xiàn)類(lèi);
  4. 很方便的重復(fù)添加特性:我想要一套兩個(gè)雞蛋,雙份辣條的煎餅。是不是只需要多裝飾一次就可以了?就是這么簡(jiǎn)單。

2.2 缺點(diǎn)

  1. 由于不是通過(guò)繼承實(shí)現(xiàn)添加職責(zé),所以被裝飾后的對(duì)象并不能通過(guò)對(duì)象本身就能了解其特性。而需要分析所有對(duì)其裝飾過(guò)的對(duì)象;
  2. 裝飾模式會(huì)造成有很多功能類(lèi)似的小對(duì)象。通過(guò)組合不同的裝飾實(shí)現(xiàn),來(lái)達(dá)成不同的需求。這樣對(duì)于不了解系統(tǒng)的人,比較難以學(xué)習(xí)。過(guò)多的裝飾類(lèi)進(jìn)行裝飾,也稍顯繁瑣。

3. 裝飾者模式適用場(chǎng)景

使用裝飾者模式,有以下幾種情況:

  1. 需要一個(gè)裝飾的載體。不能將全部特性都放在裝飾類(lèi)中。換句話講得有個(gè)裝飾主體,核心特性在主體對(duì)象中實(shí)現(xiàn)。例如瀏覽器窗口,不管是加邊框還是滾動(dòng)條,都是基于窗口的;
  2. 有多種特性可以任意搭配,對(duì)主體進(jìn)行擴(kuò)展。并且你想以動(dòng)態(tài)、透明的方式來(lái)實(shí);
  3. 不能以生成子類(lèi)的方式擴(kuò)展。可能有兩種情況,一是對(duì)大量子類(lèi)帶來(lái)的類(lèi)爆炸有所顧慮。二是類(lèi)定義被隱藏,或者不能用于生成子類(lèi)。

4. 小結(jié)

裝飾者模式的優(yōu)勢(shì)在于動(dòng)態(tài)、透明的添加特性。要記住裝飾者裝飾完的對(duì)象還是之前的對(duì)象類(lèi)型。通過(guò)分離核心特性和裝飾特性,客戶端代碼可以靈活的搭配使用包裝對(duì)象,從而得到具有想要行為的對(duì)象。不過(guò)要注意,有些時(shí)候裝飾的順序是要保證的。比如先放雞蛋,再放芝麻,芝麻就不會(huì)掉下去了。最好的做法是保證裝飾類(lèi)的獨(dú)立。