您好,登錄后才能下訂單哦!
裝飾者模式是什么與橋接模式有什么不同?針對這個問題,這篇文章詳細介紹了相對應的分析和解答,希望可以幫助更多想解決這個問題的小伙伴找到更簡單易行的方法。
拉面的故事
拉面館里賣拉面,拉面分為小碗和大碗,小碗一份6元,大碗一份9元。另外如果加牛肉的話,則需加6元,加一個雞蛋是1元,加大排是5元一份,加一塊鍋巴是1元。如果用傳統的寫法,設置不同價格的拉面,需要寫8個類(拉面份量數*配菜數)。如果現在面館新推一種份量——中碗,那么,就需要新增4個類。這樣就會造成一個問題——類爆炸。
了解了橋接模式后,會覺得這個問題可以用橋接模式來解決。把它分為兩個大類,面條和配菜。
下面我們用橋接模式來完成上述問題,代碼如下:
interface INoodle { function cost (); function desc (); } class BigNoodle implements INoodle { private $cost = 9.0; private $dish = null; public function __construct(IDish $dish) { $this->dish = $dish; } public function cost() { return $this->cost + $this->dish->cost(); } public function desc() { return $this->dish->desc() . '大碗拉面'; } } class SmallNoodle implements INoodle { private $cost = 6.0; private $dish = null; public function __construct(IDish $dish) { $this->dish = $dish; } public function cost() { return $this->cost + $this->dish->cost(); } public function desc() { return $this->dish->desc() . '小碗拉面'; } } interface IDish { function cost (); function desc (); } class Beef implements IDish { public function cost () { return 6; } public function desc() { return '牛肉'; } } class Crust implements IDish { public function cost () { return 1; } public function desc() { return '鍋巴'; } } class Egg implements IDish { public function cost () { return 1; } public function desc() { return '雞蛋'; } }
裝飾者模式
使用橋接模式確實解決了類爆炸問題,但你也知道,我們去吃面,可能有時候不要配菜,只要面,又或者我們需要多個配菜,比如,我要份大碗牛肉拉面,加3塊鍋巴以及2個雞蛋。對于這種需求,使用橋接模式是完成不了的。想要解決這種問題,我們可以借助另一種結構型設計模式——裝飾者模式。
裝飾模式是一種結構型設計模式, 允許你通過將對象放入包含行為的特殊封裝對象中來為原對象綁定新的行為。
想要理解裝飾者模式,可以想象一個玩偶——套娃
每套一個娃,就相當于添加了一個裝飾的對象。在運行時,會運行最外層的裝飾對象(取外層的娃),然后一層一層的運行。現在你可能不懂什么意思,看完后面的內容然后再來會看這句話或許就會明白。
我自己畫了個uml類圖,有點丑,大家將就點
代碼實現
abstract class Noodles { abstract function cost (); abstract function desc (); } class BigNoodle extends Noodles { private $cost = 9.0; public function cost() { return $this->cost; } public function desc() { return '大碗拉面'; } } class SmallNoodle extends Noodles { private $cost = 6.0; public function cost() { return $this->cost; } public function desc() { return '小碗拉面'; } } abstract class NoodlesDecorator extends Noodles { } class Beef extends NoodlesDecorator { private $desc = '牛肉'; private $cost = 6.0; protected $noodles = null; public function __construct(Noodles $noodels) { $this->noodles = $noodels; } public function cost () { return $this->cost + $this->noodles->cost(); } public function desc () { return $this->desc . $this->noodles->desc(); } } // egg、curst類代碼省略,除了屬性值不一樣基本和Beef一致
測試代碼如下
$noodles = new BigNoodle(); $beefBigNoodles = new Beef($noodles); $eggBeffBigNoodles = new Egg($beefBigNoodles); echo $eggBeffBigNoodles->desc(); echo $eggBeffBigNoodles->cost() . '元';
結果輸出:雞蛋牛肉大碗拉面16元
總結
思考一個問題,為什么這里沒有把拉面的份量作為裝飾者對象?想想看,你會點一份既是大碗又是小碗的拉面嗎?
裝飾者模式特點
裝飾者和被裝飾者對象有相同的超類型
可以用一個或多個裝飾者包裝一個對象
對象可以在任何時候被裝飾,所以可以在運行時動態地、不限量地用你喜歡的裝飾者來裝飾對象。
關于裝飾者模式是什么與橋接模式有什么不同問題的解答就分享到這里了,希望以上內容可以對大家有一定的幫助,如果你還有很多疑惑沒有解開,可以關注億速云行業資訊頻道了解更多相關知識。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。