• 设计模式之---装饰者模式


    装饰者模式,能够实现一个非常重要的面向对象设计原则,那就是:类应该对扩展开放,而对改动关闭。换句话说,就是在不必改变原类文件和使用继承的情况下,动态地扩展一个对象的功能。它是通过创建一个包装对象。也就是装饰来包裹真实的对象。可是在选择须要被扩展的代码部分时要小心,每一个地方都採用开放-关闭原则是一种浪费,也不是必需,还会导致代码变得复杂且难以理解。


    举个样例。比方,顾客想要摩卡和奶泡的深焙咖啡。那么要做的是:


    1。拿一个深焙咖啡(DarkRoast)对象

    2,以摩卡(Mocha)对象装饰它

    3。以奶泡(Whip)对象装饰它

    4,调用cost()方法。并依赖托付(delegate)将调料的价钱加上去


    Mocha对象是一个装饰者。它的类型“反映”了它所装饰的对象(本例中,就是Beverage)。

    所谓的“反映”,指的就是两者类型一致。

    所以Mocha也有一个cost()方法。通过多态,也能够把Mocha所包裹的不论什么Beverage当成是Beverage(由于Mocha是Beverage的子类型)。


    Whip相同也是一个装饰者,所以它也反映了DarkRoast类型,并包含一个cost()方法。


    所以。被Mocha和Whip包起来的DarkRoast对象仍然是一个Beverage。仍然能够具有DarkRoast的一切行为,包含调用它的cost()方法。


    如今该是为顾客算钱的时候了。通过调用最外圈装饰者(whip)的cost()就能够办得到。Whip的cost()会先托付它装饰的对象(也就是Mocha)计算出价钱,然后再加上奶泡的价钱。


    也就是说。

    1,先调用最外圈装饰者Whip的cost()。

    2,Whip调用Mocha的cost();

    3,Mocha调用DarkRoast的cost();

    4,DrakRoast返回它的价钱;

    5,Mocha在DarkRoast的结果上,加上自己的价钱,返回新的价钱;

    6。Whip在Mocha的返回结果上加上自己的价钱,然后返回最后结果。


    注意,

    1,装饰者和被装饰者有同样的超类型。

    2。你能够用一个或多个装饰者包装一个对象。

    3,既然装饰者和被装饰者有同样的超类型,所以在不论什么须要原始对象(被包装的)的场合,能够用装饰过的对象取代它。

    4。装饰者能够在托付被装饰者的行为之前与/或之后,加上自己的行为,以达到特定的目的;

    5,对象能够在不论什么时候被装饰。所以能够在执行时动态地、不限量地用你喜欢的装饰者来装饰对象;


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


    以下我们開始代码实现:


    首先是Beverage类:

    package decorator;
    
    public abstract class Beverage {
    	String description = "Unknown Beverage";
    	public String getDescription(){
    		return description;
    	}
    	public abstract double cost();
    }

    然后我们设计装饰者类。Condiment抽象类:

    package decorator;
    
    public abstract class CondimentDecorator extends Beverage{
    	public abstract String getDescription();
    }
    

    如今已经有了基类,于是我们来实现一些饮料:

    比方意大利特浓:

    package decorator;
    
    public class Espresso extends Beverage{
    	public Espresso(){
    		description = "Espresso";
    	}
    	public double cost(){
    		return 1.99;
    	}
    }
    

    比方综合咖啡(星巴克独家调配咖啡):

    package decorator;
    
    public class HouseBlend extends Beverage{
    	public HouseBlend(){
    		description="House Blend Coffee";
    	}
    	public double cost(){
    		return .89;
    	}
    }
    

    以下我们实现调料代码:

    先实现三种,

    Mocha:

    package decorator;
    
    public class Mocha extends CondimentDecorator{
    	Beverage beverage;
    	public Mocha(Beverage beverage){
    		this.beverage=beverage;
    	}
    	public String getDescription(){
    		return beverage.getDescription()+", Mocha";
    	}
    	public double cost(){
    		return .20+beverage.cost();
    	}
    }
    

    Soy:

    package decorator;
    
    public class Soy extends CondimentDecorator{
    	Beverage beverage;
    	public Soy(Beverage beverage){
    		this.beverage=beverage;
    	}
    	public String getDescription(){
    		return beverage.getDescription()+", Soy";
    	}
    	public double cost(){
    		return .30+beverage.cost();
    	}
    }
    

    Whip:

    package decorator;
    
    public class Whip extends CondimentDecorator{
    	Beverage beverage;
    	public Whip(Beverage beverage){
    		this.beverage=beverage;
    	}
    	public String getDescription(){
    		return beverage.getDescription()+", Whip";
    	}
    	public double cost(){
    		return .40+beverage.cost();
    	}
    }
    

    以下是调用的主类:

    package decorator;
    
    public class Starbucks {
    	public static void main(String[] arga){
    		Beverage beverage=new Espresso();
    		System.out.println(beverage.getDescription()+" $"+beverage.cost());
    		beverage = new Mocha(beverage);
    	//	beverage = new Mocha(beverage);
    		beverage = new Whip(beverage);
    		beverage = new Soy(beverage);
    		System.out.println(beverage.getDescription()+" $"+beverage.cost());
    		
    	}
    }
    


  • 相关阅读:
    Windows 8.1 Visual Studio 2013 OpenGL 配置
    panic 和 recover的区别
    Beego操作数据库
    sql 中 inner join、left join 和 right join的区别
    Go实现网页爬虫
    SqlServer中 不区分大小写 和 全半角的写法
    循环语句
    switch语句
    iota枚举
    关于Go开发工具(LiteIDE)
  • 原文地址:https://www.cnblogs.com/blfshiye/p/5059606.html
Copyright © 2020-2023  润新知