网创优客建站品牌官网
为成都网站建设公司企业提供高品质网站建设
热线:028-86922220
成都专业网站建设公司

定制建站费用3500元

符合中小企业对网站设计、功能常规化式的企业展示型网站建设

成都品牌网站建设

品牌网站建设费用6000元

本套餐主要针对企业品牌型网站、中高端设计、前端互动体验...

成都商城网站建设

商城网站建设费用8000元

商城网站建设因基本功能的需求不同费用上面也有很大的差别...

成都微信网站建设

手机微信网站建站3000元

手机微信网站开发、微信官网、微信商城网站...

建站知识

当前位置:首页 > 建站知识

装饰者模式是什么与桥接模式有什么不同

装饰者模式是什么与桥接模式有什么不同?针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。

创新互联公司是一家专注于成都做网站、成都网站建设与策划设计,青冈网站建设哪家好?创新互联公司做网站,专注于网站建设10余年,网设计领域的专业建站公司;建站业务涵盖:青冈等地区。青冈做网站价格咨询:028-86922220

拉面的故事

拉面馆里卖拉面,拉面分为小碗和大碗,小碗一份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元

总结

思考一个问题,为什么这里没有把拉面的份量作为装饰者对象?想想看,你会点一份既是大碗又是小碗的拉面吗?

装饰者模式特点

  • 装饰者和被装饰者对象有相同的超类型

  • 可以用一个或多个装饰者包装一个对象

  • 对象可以在任何时候被装饰,所以可以在运行时动态地、不限量地用你喜欢的装饰者来装饰对象。

关于装饰者模式是什么与桥接模式有什么不同问题的解答就分享到这里了,希望以上内容可以对大家有一定的帮助,如果你还有很多疑惑没有解开,可以关注创新互联行业资讯频道了解更多相关知识。


文章名称:装饰者模式是什么与桥接模式有什么不同
分享链接:http://bjjierui.cn/article/ippoco.html

其他资讯