浅谈设计模式--装饰者模式(Decorator Pattern)

挖了设计模式这个坑,得继续填上。继续设计模式之路。这次讨论的模式,是

装饰者模式(Decorator Pattern)

装饰者模式,有时也叫包装者(Wrapper),主要用于静态或动态地为一个特定的对象增加新的特性,而不影响这个对象的类(allows behavior to be added to an individual object, either statically or dynamically, without affecting the behavior of other objects from the same class)。

 

装饰者模式,主要用处是,灵活方便地增加特性到特定的对象上。请看下面的例子:

 1 /**

 2  * Coffee interface defines the functionality of Coffee implemented by decorator

 3  * @author YYC

 4  * 

 5  */

 6 public interface ICoffee {

 7 

 8     double getCost();

 9 

10     String getIngredients();

11 

12 }

13 

14 

15 /**

16  * extension of a simple coffee without any extra ingredients

17  * @author YYC

18  *

19  */

20 public class SimpleCoffee implements ICoffee{

21 

22     public double getCost() {

23         return 1;

24     }

25 

26     public String getIngredients() {

27         return "Coffee";

28     }

29 

30 }

31 

32 

33 /**

34  * abstract decorator class - note that it implement Coffee interface

35  * @author YYC

36  * 

37  */

38 public abstract class CoffeDecorator implements ICoffee {

39 

40     protected final ICoffee decoratedCoffee;

41     protected String ingredientSeparator = ",";

42 

43     public CoffeDecorator(ICoffee decoratedCoffee) {

44         this.decoratedCoffee = decoratedCoffee;

45     }

46     

47     public double getCost(){

48         return decoratedCoffee.getCost();

49     }

50     

51     public String getIngredients(){

52         return decoratedCoffee.getIngredients();

53     }

54     

55 }

 

首先对于装饰者模式而已,一个公共的接口是必须的,在这里是ICoffee,代表咖啡的抽象接口。然后需要有一个简单的实现类以及一个装饰者的抽象类,作为具体装饰者的父类。接下来的是具体的装饰者类:

 

 1 /**

 2  * Decorator Milk that mixes milk with coffee

 3  * @author YYC

 4  *

 5  */

 6 public class Milk extends CoffeDecorator {

 7 

 8     public Milk(ICoffee decoratedCoffee) {

 9         super(decoratedCoffee);

10     }

11 

12     public double getCost() {

13         return super.getCost() + 0.5;

14     }

15 

16     public String getIngredients() {

17         return super.getIngredients() + ingredientSeparator + "Milk";

18     }

19 

20 }

21 

22 

23 /**

24  * @author YYC 

25  * Decorator Sprinkles that mixes sprinkles with coffee

26  */

27 public class Sprinkles extends CoffeDecorator {

28 

29     public Sprinkles(ICoffee decoratedCoffee) {

30         super(decoratedCoffee);

31     }

32 

33     public double getCost() {

34         return super.getCost() + 1.2;

35     }

36 

37     public String getIngredients() {

38         return super.getIngredients() + ingredientSeparator + "Sprinkles";

39     }

40 

41 }

 

具体的装饰者类,继承抽象装饰者类,并具体实现抽象装饰者类的方法,达到将新的特性(milk/sprinkles)加到原来的类(coffee)的目的。

public class Main {



    public static void main(String[] args) {



        ICoffee c = new SimpleCoffee();

        System.out.println("Cost: " + c.getCost() + "; Ingredients: " + c.getIngredients());



        c = new Milk(c);

        System.out.println("Cost: " + c.getCost() + "; Ingredients: " + c.getIngredients());

        

        c = new SimpleCoffee();

        c = new Sprinkles(c);

        System.out.println("Cost: " + c.getCost() + "; Ingredients: " + c.getIngredients());



        c=new SimpleCoffee();

        c = new Milk(new Sprinkles(c));

        System.out.println("Cost: " + c.getCost() + "; Ingredients: " + c.getIngredients());



    }



}



/*

 * output:

 * Cost: 1.0; Ingredients: Coffee

 * Cost: 1.5; Ingredients: Coffee,Milk

 * Cost: 2.2; Ingredients: Coffee,Sprinkles

 * Cost: 2.7; Ingredients: Coffee,Sprinkles,Milk

 */

 

抽象类理解起来并不困难,而且相当实用,很多时候比创建子类更加灵活。在Java里java.io.BufferedReader/FileReader/Reader都有使用这个模式。

 

以下情况使用Decorator模式

1. 需要扩展一个类的功能,或给一个类添加附加职责。

2. 需要动态的给一个对象添加功能,这些功能可以再动态的撤销。

3. 需要增加由一些基本功能的排列组合而产生的非常大量的功能,从而使继承关系变的不现实。

4. 当不能采用生成子类的方法进行扩充时。一种情况是,可能有大量独立的扩展,为支持每一种组合将产生大量的子类,使得子类数目呈爆炸性增长。另一种情况可能是因为类定义被隐藏,或类定义不能用于生成子类。

 

优点:

1. Decorator模式与继承关系的目的都是要扩展对象的功能,但是Decorator可以提供比继承更多的灵活性。

2. 通过使用不同的具体装饰类以及这些装饰类的排列组合,设计师可以创造出很多不同行为的组合。

缺点:

1. 这种比继承更加灵活机动的特性,也同时意味着更加多的复杂性。

2. 装饰模式会导致设计中出现许多小类,如果过度使用,会使程序变得很复杂。

3. 装饰模式是针对抽象组件(Component)类型编程。但是,如果你要针对具体组件编程时,就应该重新思考你的应用架构,以及装饰者是否合适。当然也可以改变Component接口,增加新的公开的行为,实现“半透明”的装饰者模式。在实际项目中要做出最佳选择。

 

参考:

http://javapapers.com/design-patterns/decorator-pattern/

http://www.cnblogs.com/god_bless_you/archive/2010/06/10/1755212.html

你可能感兴趣的:(Decorator)