装饰者模式是什么与桥接模式有什么不同
导读:本文共2766.5字符,通常情况下阅读需要9分钟。同时您也可以点击右侧朗读,来听本文内容。按键盘←(左) →(右) 方向键可以翻页。
摘要: 拉面的故事拉面馆里卖拉面,拉面分为小碗和大碗,小碗一份6元,大碗一份9元。另外如果加牛肉的话,则需加6元,加一个鸡蛋是1元,加大排是5元一份,加一块锅巴是1元。如果用传统的写法,设置不同价格的拉面,需要写8个类(拉面份量数*配菜数)。如果现在面馆新推一种份量——中碗,那么,就需要新增4个类。这样就会造成一个问题——类爆炸。了解了桥接模式后,会觉得这个问题可以用桥... ...
目录
(为您整理了一些要点),点击可以直达。拉面的故事
拉面馆里卖拉面,拉面分为小碗和大碗,小碗一份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元
总结
思考一个问题,为什么这里没有把拉面的份量作为装饰者对象?想想看,你会点一份既是大碗又是小碗的拉面吗?
装饰者模式特点
</div> <div class="zixun-tj-product adv-bottom"></div> </div> </div> <div class="prve-next-news">
装饰者模式是什么与桥接模式有什么不同的详细内容,希望对您有所帮助,信息来源于网络。