zoukankan      html  css  js  c++  java
  • 设计模式-装饰模式

    之前写Python的时候,用到了装饰器,然后不由自主想到了设计模式中的装饰模式,正好最近一直在看设计模式,就记录下自己的一些理解。如有错误,欢迎指正。

    装饰模式

    比较官方的定义是这样的

    装饰模式是在不必改变原类文件和使用继承的情况下,动态地扩展一个对象的功能。它是通过创建一个包装对象,也就是装饰来包裹真实的对象

    装饰,装饰嘛,很显然你只想让别人看见最终装饰的东西,并不像让别人看见你的装饰过程。打个比方说,你去餐馆吃饭,很明显主要是吃饭,当然光吃米饭,肯定难以下咽了,你想了想准备吃青椒肉丝盖浇饭,然后餐馆厨房开始做了,这个时候你想去厨房去瞧一瞧,你发现厨房门上贴着“非工作人员入内”,意思很明显嘛,餐馆并不希望我去参观他做盖浇饭的过程,谁知道中间有什么猫腻,最后呈现在我面前的就是我自己点的那份青椒肉丝盖浇饭,当然盖浇饭不止这一种还有番茄鸡蛋盖浇饭啊,鱼香肉丝盖浇饭啊。。。不过厨房加工的地方不让看。

    类图是这样的:

    可以把Component看作一个食物,ConcreteComponent看作米饭,Decorator则可以看作加工过程,ConcreteDecoratorA(B)就是各种食物素材啦。
    对于Componet是无需知道Decorator存在的。
    如果只有一个ConcreteComponent类而没有抽象的Component类,那么Decorator类可以是ConcreteComponent的一个子类。同样如果只有一个ConcreteDecorator
    ,那么也没有必要建立一个单独的Decorator,而可以把Decorator和ConcreteDecorator的责任合并成一个类。

    这个时候的类图,如下:

    和这样

    顺便说下starUML类图中部分符号的含义:

    1. 类 ( Class ) :三层矩形框表示,第一层类名,如果是抽象类,是用斜体表示的;第二层是字段和属性;第三层则是类方法,其中"+"表示该方法是public的,“-”表示private,“#”表示protected
    2. 继承类():用空心三角形+实现来表示

    Talk is cheap,show me the code:

    <?php
    abstract class food
    {
    	public $_name;
    	abstract public function cook();
    }
    
    //被装饰的类
    class rice extends food
    {
    	public function __construct()
    	{
    		$this->_name = 'rice';
    	}
    
    	public function cook()
    	{
    		return "cooked_rice";
    	}
    }
    
    //盖浇饭decorator
    class fooddecorator extends food
    {
    	public function __construct()
    	{
    		$this->_name = 'fooddecorator';
    	}
    
    	public function cook(){
    		return "cooking";
    	}
    } 
    
    //青椒
    class  capsicum extends fooddecorator
    {
    	public $_food;
    	public function __construct($food)
    	{
    		$this->_name = 'capsicum';
    		if($food instanceof food)
    		{
    			$this->_food = $food;
    		}else{
    			return false;
    		}
    	}
    
    	public function cook()
    	{
    		return $this->_food->cook()." cooked_capsicum";
    	}
    }
    
    //肉丝
    class meat extends fooddecorator
    {
    	public $_food;
    	public function __construct($food)
    	{
    		$this->_name = 'meat';
    		if($food instanceof food)
    		{
    			$this->_food = $food;
    		}else{
    			return false;
    		}
    	}
    
    	public function cook()
    	{
    		return $this->_food->cook()." cooked_meat";
    	}
    }
    
    //qr 青椒加饭 qjrs means 青椒肉丝
    $rice = new rice();
    //加青椒
    $qr = new capsicum($rice);
    //加肉
    $qjrs = new meat($qr);
    
    echo "fried green peppers:".$qjrs->cook();
    ?>
    

    结果:

    好像忘记加盐了~0.0
    装饰模式是围绕一个核心,然后动态装饰这个核心,很明显盖浇饭的核心是饭,在饭上加不同的菜,产生了不同的盖浇饭
    这个时候估计有人说了,我不用装饰模式也可以实现着个过程啊~
    然后写了这样的代码:

    <?php
    abstract class food
    {
    	public $_name;
    	abstract public function cook();
    }
    
    class rice extends food
    {
    	public function __construct()
    	{
    		$this->_name = 'rice';
    	}
    
    	public function cook()
    	{
    		return " cooked_rice";
    	}
    }
    
    class capsicum extends food
    {
    	public function __construct()
    	{
    		$this->_name = 'capsicum';
    	}
    
    	public function cook()
    	{
    		return " cooked_capsicum";
    	}
    }
    
    class meat extends food
    {
    	public function __construct()
    	{
    		$this->_name = 'meat';
    	}
    
    	public function cook()
    	{
    		return " cooked_meat";
    	}
    }
    
    $rice = new rice();
    $capsicum = new capsicum();
    $meat = new meat();
    echo "fried green peppers:".$rice->cook().$capsicum->cook().$meat->cook();
    ?>
    

    结果很明显跟上面一样但是没有区别吗很明显第二种方法,第二种方法暴露了你做盖浇饭的顺序,就相当于顾客悄悄溜进厨房,看着厨师把盖浇饭做好了,见证了这一从无到有的过程,因此我们需要用装饰模式,将这加工处理的工程隐藏起来,只有这一个区别吗?很明显并不是,第二种方法三个子类处于同级,不分主次,但是不要忘了,顾客是去吃米饭的,之所以要了盖浇饭是为了让米饭更好吃,如果真的没有菜,做不成盖浇饭,只吃米顾客还是可以接受的,但是要是没有米,光有菜可不行,米饭是前提条件。要是觉得难以接受这个设定,就把盖浇饭换成各种类型的粥吧,绿豆粥,红薯粥。。。,要是少了米,还能叫粥吗。

    最后做下简单的总结

    装饰模式总结

    1.装饰模式是向原有的类,动态的添加新的功能。
    2.把类中的装饰功能从类中移去,是简化了原有类。
    3.跟继承的区别,装饰模式是围绕着一个核心,在该核心存在的情况下去进行的,存在主次的关系,而继承所有子类处于同级
    4.装饰模式的装饰顺序也是很重要,继承则不存在这种问题。比如说,穿衣服,你应该先穿内衣,再穿外套,而不是任意顺序。
    5.多用组合,少用继承

  • 相关阅读:
    洛谷1052——过河(DP+状态压缩)
    mod4最优路径问题(转载)
    初次接触python,怎么样系统的自学呢?
    对AM信号FFT的matlab仿真
    初次使用自己写的testbench 验证了简单的NOT门。
    写简单的tb(testbench)文件来测试之前的FSM控制的LED
    利用简单的有限状态机(FSM)来实现一个简单的LED流水灯
    利用状态机(FSM)进行简单的uart串口发送数据
    用matlab脚本语言写M文件函数时用三种方法简单实现实现DFT(离散傅里叶变换)
    作为新手对于初次接触matlab的一些感受。
  • 原文地址:https://www.cnblogs.com/leetao94/p/5347282.html
Copyright © 2011-2022 走看看