`
cuixuxucui
  • 浏览: 346436 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

装饰模式

阅读更多

参考http://www.cnblogs.com/xinye/p/3910149.html

http://www.2cto.com/kf/201512/455764.html

 

假如有个食物类,不同的做法蒸炒煎炸要生成不同的基类。就是四个子类:蒸食物、炒食物,煎食物,炸食物。如果还要有两种做法的子类呢,还要写蒸炒食物,蒸煎食物……三种做法的更夸张,子类多到爆炸。并且为了应对不同情况,要把所有可能用到的子类都提前写出来,而不是到使用时再随时写。

处理办法:

食物类增加四个属性来标记做法:是否蒸,是否炒,是否煎,是否炸……

那要是有蒸两遍的呢?看来这个属性不能用bool类型,还要用int类型。

当然这样做,对应不同的做法组合,处理方法里要写很多if判断上述的四个属性组合,去做对应的逻辑。食物类也因此变得庞大,逻辑超多。如果需要40个属性,甚至400个属性呢……这种直接在基类中处理所有逻辑也违反了开放封闭原则,即基类是可扩展的,但不能修改。可以预见到,随着食物的做法增多,必然要不停地修改基类,以及基类的if判断。

 

有没有办法做到,生成一个食物的子类,即满足子类要求,又可以处理不同的做法呢。答案就是组合,即设计模式中的装饰模式。

 

1.abstract class Food食物类

   function todo()

2.Chicken extends Food鸡肉类

3.Duck extends Food鸭肉类

 

4.FoodDecoration extends Food

 

5.SteameFood extends FoodDecoration//子类蒸食物,仍然是Food的子类

   private Food food;//使用构造方法传入的变量进行组合

   public SteameFood(Food f){

      this.food = f;

   }

   override function todo(){

      //food.todo()

      //蒸

   }

6.RoastFood extends FoodDecoration//子类烤食物,仍然是Food的子类

   private Food food;//使用构造方法传入的变量进行组合

   public RoastFood(Food f){

      this.food = f;

   }

   override function todo(){

      //food.todo()

      //烤

   }

 

运行时就可以自由组合了:

 

// 测试单纯的食物

Food f1 = new Chicken();

System.out.println(f1.getDesc());

System.out.println("----------------------");

 

// 测试单重修饰的食物

RoastFood rf = new RoastFood(f1);

System.out.println(rf.getDesc());

System.out.println("----------------------");

 

// 测试多重修饰的食物

SteamedFood sf = new SteamedFood(rf);

System.out.println(sf.getDesc());

 

执行结果:

鸡肉

----------------------

烤鸡肉

----------------------

蒸烤鸡肉

 

可以看出,N种做法只要N个子类。使用的时候多重装饰即可,自己安排好装饰顺序。

 

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics