首页 > Java开发 > 设计模式之—装饰者模式

设计模式之—装饰者模式

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

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

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类:

[java]

  1. package decorator;  
  2.   
  3. public abstract class Beverage {  
  4.     String description = "Unknown Beverage";  
  5.     public String getDescription(){  
  6.         return description;  
  7.     }  
  8.     public abstract double cost();  
  9. }  


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

[java]

  1. package decorator;  
  2.   
  3. public abstract class CondimentDecorator extends Beverage{  
  4.     public abstract String getDescription();  
  5. }  


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

比如意大利特浓:

[java]

  1. package decorator;  
  2.   
  3. public class Espresso extends Beverage{  
  4.     public Espresso(){  
  5.         description = "Espresso";  
  6.     }  
  7.     public double cost(){  
  8.         return 1.99;  
  9.     }  
  10. }  


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

[java]

  1. package decorator;  
  2.   
  3. public class HouseBlend extends Beverage{  
  4.     public HouseBlend(){  
  5.         description="House Blend Coffee";  
  6.     }  
  7.     public double cost(){  
  8.         return .89;  
  9.     }  
  10. }  


下面我们实现调料代码:

先实现三种,

Mocha:

[java]

  1. package decorator;  
  2.   
  3. public class Mocha extends CondimentDecorator{  
  4.     Beverage beverage;  
  5.     public Mocha(Beverage beverage){  
  6.         this.beverage=beverage;  
  7.     }  
  8.     public String getDescription(){  
  9.         return beverage.getDescription()+", Mocha";  
  10.     }  
  11.     public double cost(){  
  12.         return .20+beverage.cost();  
  13.     }  
  14. }  


Soy:

[java]

  1. package decorator;  
  2.   
  3. public class Soy extends CondimentDecorator{  
  4.     Beverage beverage;  
  5.     public Soy(Beverage beverage){  
  6.         this.beverage=beverage;  
  7.     }  
  8.     public String getDescription(){  
  9.         return beverage.getDescription()+", Soy";  
  10.     }  
  11.     public double cost(){  
  12.         return .30+beverage.cost();  
  13.     }  
  14. }  


Whip:

[java]

  1. package decorator;  
  2.   
  3. public class Whip extends CondimentDecorator{  
  4.     Beverage beverage;  
  5.     public Whip(Beverage beverage){  
  6.         this.beverage=beverage;  
  7.     }  
  8.     public String getDescription(){  
  9.         return beverage.getDescription()+", Whip";  
  10.     }  
  11.     public double cost(){  
  12.         return .40+beverage.cost();  
  13.     }  
  14. }  


下面是调用的主类:

[java]

  1. package decorator;  
  2.   
  3. public class Starbucks {  
  4.     public static void main(String[] arga){  
  5.         Beverage beverage=new Espresso();  
  6.         System.out.println(beverage.getDescription()+" $"+beverage.cost());  
  7.         beverage = new Mocha(beverage);  
  8.     //  beverage = new Mocha(beverage);  
  9.         beverage = new Whip(beverage);  
  10.         beverage = new Soy(beverage);  
  11.         System.out.println(beverage.getDescription()+" $"+beverage.cost());  
  12.           
  13.     }  
  14. }  

本文固定链接: http://www.devba.com/index.php/archives/6026.html | 开发吧

报歉!评论已关闭.