成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

通俗易懂的談?wù)勓b飾器模式

forsigner / 547人閱讀

摘要:裝飾器模式允許向一個(gè)現(xiàn)有的對象添加新的功能,同時(shí)又不改變其結(jié)構(gòu)。這便是裝飾模式,通過一層一層的裝飾,我們可以靈活的得到我們想要的結(jié)果。可以輕松的添加新的裝飾器類或者新的組件來創(chuàng)建靈活的結(jié)構(gòu)。

前言

在編碼的時(shí)候,我們?yōu)榱藬U(kuò)展一個(gè)類經(jīng)常是使用繼承方式來實(shí)現(xiàn),隨著擴(kuò)展功能的增多,子類會越來越膨脹,使系統(tǒng)變得不靈活。

裝飾器模式( Decorator Pattern )允許向一個(gè)現(xiàn)有的對象添加新的功能,同時(shí)又不改變其結(jié)構(gòu)。它能讓我們在擴(kuò)展類的時(shí)候讓系統(tǒng)較好的保持靈活性。

那么裝飾器模式具體是什么樣的呢?

從一個(gè)情景開始

我們有一塊地,在這塊地上,我們要蓋一棟有好幾間房間的別墅,每間房間的裝修費(fèi)用都不同,現(xiàn)在,我們要對蓋別墅的費(fèi)用進(jìn)行計(jì)算。

先定義一個(gè)Land類,表示這塊地,Land類定義了在這塊地上蓋別墅需要花錢這個(gè)規(guī)則。

abstract class Land
{
    abstract public function cost();
}

Land已經(jīng)定義好了在這塊地上蓋房需要花錢的這個(gè)規(guī)則了,但是蓋一間房間具體花多少錢呢?

此時(shí)我們再定義一個(gè)Room類,這個(gè)類具體的定義了一個(gè)房間建造的基本費(fèi)用(一個(gè)最簡單房間,里面啥也沒有的)。

class Room extends Land
{
    private $money = 1000;
    public function cost()
    {
        return $this->money;
    }
}

然后開始建造房間,我們建了兩個(gè)房間,分別是客廳和餐廳,用LivingRoom類和DiningRoom類來表示

class LivingRoom extends Room
{
    public function cost()
    {
        return parent::cost()+200; //客廳的建造費(fèi)用在房屋建造費(fèi)用的基礎(chǔ)上多200,比如要買沙發(fā),電視
    }
    
}

class DiningRoom extends Room
{
    public function cost()
    {
        return parent::cost()+100; //餐廳的建造費(fèi)用在房屋建造費(fèi)用的基礎(chǔ)上多100,比如買餐桌
    }
}

現(xiàn)在,我們很容易就能得到建造一間客廳所需的花費(fèi)

$livingRoomCost = new LivingRoom();
echo $livingRoomCost->cost();
問題的產(chǎn)生

不過,這樣的結(jié)構(gòu)并不具備靈活性,雖然我們可以很容易的分別得出建造一間客廳和建造一間餐廳的費(fèi)用,但是,如果我買的地比較小,只能把餐廳和客廳建在同一個(gè)房間里,那要怎么去計(jì)算費(fèi)用?難道還要很麻煩的去創(chuàng)建一個(gè)包含客廳和餐廳的LivingDiningRoom類?這樣做的話除了麻煩,還會使代碼產(chǎn)生重復(fù)。

解決問題

為了更好的解決這個(gè)問題,我們得做一些調(diào)整,同樣先聲明Land類和Room類,不同的是,引入了一個(gè)房間的裝飾類RoomDecorator,它繼承了Land類,因?yàn)闆]有實(shí)現(xiàn)Land類的cost()方法,所以需將它聲明為抽象類,并且定義了一個(gè)以Land類的對象為參數(shù)的構(gòu)造方法,傳入的對象會保存在$land屬性中,該屬性聲明為protected,以便子類訪問。具體如下。

abstract class RoomDecorator extends Land
{
    protected $land;
    public function __construct(Land $land)
    {
        $this->land = $land;
    }
}

然后我們再重新定義客廳類和餐廳類

class LivingRoom extends RoomDecorator
{
    public function cost()
    {
        return $this->land->cost()+200;
    }
}


class DiningRoom extends RoomDecorator
{
    public function cost()
    {
        return $this->land->cost()+100;
    }
}

這兩個(gè)類都擴(kuò)展自RoomDecorator類,這意味著它們都擁有指向Land對象的引用。當(dāng)它們的cost()方法被調(diào)用時(shí),都會先調(diào)用所引用的Land類對象的cost()方法,然后再執(zhí)行自己特有的操作。

所以這時(shí)候,建造一間客廳所需的費(fèi)用是這樣計(jì)算

$livingRoomCost = new LivingRoom(new Room());
echo $livingRoomCost->cost(); //輸出1200

建造一間餐廳所需的費(fèi)用是這樣計(jì)算

$diningRoomCost = new DiningRoom(new Room());
echo $diningRoomCost->cost(); //輸出1100

回到剛才的問題,如果我們需計(jì)算建造一間包含客廳餐廳的房間所需費(fèi)用,代碼如下

$livingRoom = new DiningRoom(new LivingRoom(new Room()));
echo $livingRoom->cost(); //輸出1300

看,我們現(xiàn)在計(jì)算建造費(fèi)用的思路是:計(jì)算出基礎(chǔ)房間的費(fèi)用 --> 在基礎(chǔ)房間上裝飾成客廳的費(fèi)用 --> 在客廳的基礎(chǔ)上加裝飾餐廳的費(fèi)用 --> 得到包含客廳餐廳的房間費(fèi)用。已經(jīng)不需要麻煩的通過創(chuàng)建一個(gè)LivingDiningRoom類來計(jì)算包含客廳餐廳的房間建造費(fèi)用了。

這便是裝飾模式,通過一層一層的裝飾,我們可以靈活的得到我們想要的結(jié)果。可以輕松的添加新的裝飾器類或者新的組件來創(chuàng)建靈活的結(jié)構(gòu)。

完整代碼
money;
    }
}

//裝飾器
abstract class RoomDecorator extends Land
{
    protected $land;
    public function __construct(Land $land)
    {
        $this->land = $land;
    }
}

class LivingRoom extends RoomDecorator
{
    public function cost()
    {
        return $this->land->cost()+200;
    }
}


class DiningRoom extends RoomDecorator
{
    public function cost()
    {
        return $this->land->cost()+100;
    }
}

$livingRoomCost = new LivingRoom(new Room());
echo $livingRoomCost->cost(); //輸出1200

$diningRoomCost = new DiningRoom(new Room());
echo $diningRoomCost->cost(); //輸出1100

$livingDining = new DiningRoom(new LivingRoom(new Room()));
echo $livingDining->cost(); //輸出1300

the end.

happy coding! ^_^

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/25853.html

相關(guān)文章

  • 通俗易懂設(shè)計(jì)模式

    摘要:面向?qū)ο笤O(shè)計(jì)模式通常以類別或?qū)ο髞砻枋銎渲械年P(guān)系和相互作用,但不涉及用來完成應(yīng)用程序的特定類別或?qū)ο蟆@锸洗鷵Q原則里氏代換原則是面向?qū)ο笤O(shè)計(jì)的基本原則之一。 通俗易懂的設(shè)計(jì)模式 零、使用 1、安裝 2、測試 一、什么是設(shè)計(jì)模式 二、設(shè)計(jì)模式的類型 三、設(shè)計(jì)模式的六大原則 四、UML類圖 1、看懂UML類圖 2、解釋 五、資料 前言:花了一些時(shí)間再次熟悉了一遍...

    wuyangnju 評論0 收藏0
  • 從Express到Nestjs,談?wù)?/em>Nestjs設(shè)計(jì)思想和使用方法

    摘要:三的洋蔥模型這里簡單講講在中是如何分層的,也就是說請求到達(dá)服務(wù)端后如何層層處理,直到響應(yīng)請求并將結(jié)果返回客戶端。從而使得端支持跨域等。 ??最近已經(jīng)使用過一段時(shí)間的nestjs,讓人寫著有一種java spring的感覺,nestjs可以使用express的所有中間件,此外完美的支持typescript,與數(shù)據(jù)庫關(guān)系映射typeorm配合使用可以快速的編寫一個(gè)接口網(wǎng)關(guān)。本文會介紹一下作...

    chanjarster 評論0 收藏0
  • 從Express到Nestjs,談?wù)?/em>Nestjs設(shè)計(jì)思想和使用方法

    摘要:三的洋蔥模型這里簡單講講在中是如何分層的,也就是說請求到達(dá)服務(wù)端后如何層層處理,直到響應(yīng)請求并將結(jié)果返回客戶端。從而使得端支持跨域等。 ??最近已經(jīng)使用過一段時(shí)間的nestjs,讓人寫著有一種java spring的感覺,nestjs可以使用express的所有中間件,此外完美的支持typescript,與數(shù)據(jù)庫關(guān)系映射typeorm配合使用可以快速的編寫一個(gè)接口網(wǎng)關(guān)。本文會介紹一下作...

    wawor4827 評論0 收藏0
  • 編程中那些經(jīng)典套路——設(shè)計(jì)模式匯總

    摘要:如果看不懂的話,可以在評論區(qū)中提問,我會第一時(shí)間回答你無論何時(shí)我一直都在嗯哼該文章屬于編程中的那些經(jīng)典套路設(shè)計(jì)模式匯總系列 在正式閱讀前,我先談?wù)勎覀冊撚檬裁醋藙莺托膽B(tài)學(xué)習(xí)設(shè)計(jì)模式: 如果你還沒有過多的編程經(jīng)驗(yàn)(泛指半年以下),我建議你把它當(dāng)做小說來看,能看懂多少是多少,因?yàn)榘肽暌韵陆?jīng)驗(yàn)的程序員用到設(shè)計(jì)模式的情況只會出現(xiàn)在面試上,至于實(shí)際工作中?相對來說這部分不會由你負(fù)責(zé)。 如果你已...

    youkede 評論0 收藏0

發(fā)表評論

0條評論

最新活動(dòng)
閱讀需要支付1元查看
<