• 装饰者模式


    转载请注明出处!!。http://blog.csdn.net/zhonghuan1992

             全部配套代码均在github上:https://github.com/ZHONGHuanGit/DesignPattern




    跟着ZHONGHuan学习设计模式

    装饰者模式









             装饰者(Decorator)模式又叫包装模式。用组合的方式来拓展对象的功能,是继承关系的一个替代方案。

    定义说明:装饰者模式动态地将责任附加到对象上,若要扩展功能,装饰着提供了比继承更富有弹性的替代方案。

    从实例中体会

             实例来自 HeadFirst一书(建议读该书。样例太赞了)。是星巴克的样例。

    星巴克的咖啡非常有名(穷学生,如今喝不起o(╯□╰)o)。

    他们供应非常多种类的咖啡。

    一開始他们的类设计是以下这种。

            

             可是由于购买咖啡的时候,会增加更重调料,比方:蒸奶(Steamed Milk)。豆浆(Soy),摩卡(Mocha,也就是巧克力风味的),或者覆盖奶泡。星巴克会针对不同的调料收取不一样的费用。所以订单系统必须考虑这些。想想,一開始我们遇到这样的问题会怎么做,让每一个特别的咖啡豆+调料都自成一个类,似乎能够解决这个问题。可是。假设调料非常多,咖啡豆种类不少的话,总的类的数量=咖啡豆种类*调料数量。事实上挺多类的。这样是不行的。    

             那怎么办。在Beverage本身下手?设计成以下这种结构?

            

             学了开闭原则(忘了能够看这里)。我们明确,这样的做法违法了开闭原则。另一点。还记得组合复用原则么?优先使用组合而不是继承。这里。应该优先考虑组合。

             在这里使用装饰者模式来解决。它是这种。最先開始,我们选择咖啡豆种类。这里选择种类1

             然后加入了摩卡(Mocha)调料。使用摩卡(Mocha)来装饰咖啡豆1

             接着,再加点牛奶(milk),


             当计算价格的时候。我们从咖啡豆開始算起到最外面,或者从最外面開始算起到最里面,都可以算出价格来。

    装饰者模式类图:

            

    从上面的类图中。有四个角色:

    1 抽象构件(Component):给出一个抽象接口,以规范准备接收附加责任的对象

    2 详细构件(ConcreteComponent):定义一个将要接受附加东西的类

    3 装饰角色(Decorator):一般的装饰者,详细给详细构件装饰的任务延迟到详细装饰者

    4 详细装饰者(ConcreteDecorator):通过持有详细构件。附加给详细构件一些方法和属性。

    针对上面的样例。我们的解决方式的类图为:

            

    解决方式的代码吐下:

    interface Beverage{
    	String description = "unknown beverage";
    	public String getDescription();//返回描写叙述的
    	public double cost();//返回价格的
    }
    
    class CoffeeBean1 implements Beverage{
    	String description = "选了咖啡豆1:";
    	public String getDescription(){
    		return description;
    	}
    	public double cost(){
    		return 30;//基本价格30元
    	}
    }
    
    class CoffeeBean2 implements Beverage{
    	String description = "选了咖啡豆2:";
    	public String getDescription(){
    		return description;
    	}
    	public double cost(){
    		return 28;//基本价格28元
    	}
    }
    
    class Decorator implements Beverage{
    	String description = "unknown 装饰";
    	Beverage beverage;
    	public String getDescription(){
    		return description;
    	}
    	public double cost(){
    		return 0;//由子类来决定详细的装饰价格
    	}
    }
    
    class Milk extends Decorator{
    	String description = "加了牛奶";
    	public Milk(Beverage beverage){
    		this.beverage=beverage;
    	}
    	public String getDescription(){
    		return beverage.getDescription()+"
    "+description;//还有被装饰者的描写叙述
    	}
    	public double cost(){
    		return 5+beverage.cost();//加牛奶的价格是5元,还得加上里面beverage的价格
    	}
    }
    class Soy extends Decorator{
    	String description = "加了豆浆";
    	public Soy(Beverage beverage){
    		this.beverage=beverage;
    	}
    	public String getDescription(){
    		return beverage.getDescription()+"
    "+description;//还有被装饰者的描写叙述
    	}
    	public double cost(){
    		return 4+beverage.cost();//加豆浆的价格是4元,还得加上里面beverage的价格
    	}
    }
    class Mocha extends Decorator{
    	String description = "加了摩卡";
    	public Mocha(Beverage beverage){
    		this.beverage=beverage;
    	}
    	public String getDescription(){
    		return  beverage.getDescription()+"
    "+description;//还有被装饰者的描写叙述
    	}
    	public double cost(){
    		return 6+beverage.cost();//加摩卡的价格是6元,还得加上里面beverage的价格
    	}
    }
    


    測试代码:

    public class Main{
    	public static void main(String[] args){
    		Beverage coffee=new CoffeeBean1();//一開始选了咖啡豆1
    		coffee=new Mocha(coffee);//加了摩卡
    		coffee=new Milk(coffee);//加了牛奶
    		System.out.println(coffee.getDescription());
    		System.out.println("咖啡的价格为:"+coffee.cost());
    	}
    }
    




    结果:

    何时使用装饰者模式:

             1须要扩展一个类的功能。或给一个类添加附加责任。

             2须要动态的给一个对象添加功能,这些功能能够再动态地撤销。

             3须要添加一些基本功能的排列组合而产生的很大量的功能,从而使继承变得不现实。

    装饰者模式长处:

             1装饰者模式与继承关系的目的都是要扩展对象的功能,可是装饰者模式能够提供比继承很多其它的灵活性。装饰者模式同意系统动态的决定是否须要装饰。而继承关系早系统执行前就决定了。

             2通过使用不同的装饰者的排列组合,能够有非常多的组合。

    缺点装饰者模式会导致设计中出现很多小对象。假设过度使用,会让程序变的更复杂。而且很多其它的对象会是的差错变得困难,特别是这些对象看上去都非常像。

  • 相关阅读:
    windows服务器下安装APC
    (经验)在CSS中定义超链接样式a:link、a:visited、a:hover、a:active的顺序
    网站访问计数器
    网站计数器代码(jsp版本)
    .NET2.0隐形的翅膀,正则表达式搜魂者
    PHP中array数组教程
    [Python] py2exe先知其然
    [Python] Ubuntu12.04LTS
    [Python] 中文
    [linux] is not in the sudoers file
  • 原文地址:https://www.cnblogs.com/gavanwanggw/p/6818718.html
Copyright © 2020-2023  润新知