读书人

装饰模式终竟有什么用

发布时间: 2012-12-15 15:16:03 作者: rapoo

装饰模式究竟有什么用?
这两天在看装饰模式,例子倒是看懂了,但没明白究竟为什么要用它。
普通的解释是可以减少子类,不必继承现有的类,但你为此写的装饰类难道不是类吗,有一种用途就要写一个装饰类,依我浅薄的理解,只是应了开闭原则而已,不必修改现有类,把新的任务委派给已有的组件类,然后添加一些行为,不知我理解是否正确。

为了便于说明,请参照http://www.jdon.com/designpatterns/decorator.htm,谢谢
[最优解释]
decorate模式理解为减少子类有问题~
事实上,decorate模式主要应用于解决如下问题:
1.在不影响其他对象的情况下,以动态、透明的方式给单个对象添加职责。
2.处理那些可以撤销的职责。

以下两种情况不适于使用decorate模式:
1. 可能有大量独立的扩展,为支持每一种组合将产生大量的子类,使得子类数目呈爆炸性增长(LZ提到的情况)
2. 因为类定义被隐藏,或类定义不能用于生成子类

[其他解释]
这种需求,LZ用observe模式的思想确实可以很好的解决

coffee是基类,它拥有cost方法,这是coffee的基类方法
icecoffee继承coffee,它拥有加冰的方法addIce
milkcoffee继承coffee,它拥有加奶的方法addMilk
sugarcoffee继承coffee,它拥有加糖的方法addSugar

我现在想要一个对象,它具有icecoffee和milkcoffee的特点,即addIce和addMilk
我又想要一个对象,它具有icecoffee和sugarcoffee的特点,即addIce和addSugar
然后还有一个对象,它具有milkcoffee和sugarcoffee的特点,即addMilk和addSugar
然后,还有一个对象,它具有以上三种继承类的特点

弱问,list<coffee> how to solve this?
其实GOF和前面提到的blog都说的很清楚了
建议LZ先认真学习下





[其他解释]
其实你的疑问是对的

因为这个模式偏向于是一个重构型模式。
[其他解释]
是的,可以保留原有行为的基础上添加一些行为
或者 替换原有的行为
[其他解释]
这个模式现实中用的好像不多,new来new去的也不是很优雅
[其他解释]
装饰=装修+掩饰


[其他解释]
抱歉,上面大了个不字。。。

以下两种情况适于使用decorate模式:
1. 可能有大量独立的扩展,为支持每一种组合将产生大量的子类,使得子类数目呈爆炸性增长(LZ提到的情况)
2. 因为类定义被隐藏,或类定义不能用于生成子类

[其他解释]
使用著名的coffer的例子可能好理解一点
下面这个case:
Coffee(咖啡)、MilkCoffee(加奶咖啡)、IceCoffee(加冰咖啡)、MilkIceCoffee(加冰和奶的咖啡)

使用继承,我们可能需要如下集成体系:
Coffee
Milkcoffee IceCoffee
MilkIceCoffee
如果组合数一多,就可能面临子类膨胀
而是用decorate模式则没有这种问题。

有一篇blog,LZ可以参考:http://blog.csdn.net/hivon/archive/2008/05/27/2485072.aspx

[其他解释]

引用:
使用著名的coffer的例子可能好理解一点
下面这个case:
Coffee(咖啡)、MilkCoffee(加奶咖啡)、IceCoffee(加冰咖啡)、MilkIceCoffee(加冰和奶的咖啡)

使用继承,我们可能需要如下集成体系:
Coffee
Milkcoffee IceCoffee
MilkIceCoffee
如果组合数一多,就可能面……

你这个例子我在head first design patterns里也看到了,不过我认为处理组合的时候,完全可以不定义新的类来实现,比如可以在一个方法中使用List<Coffee>作为参数,这样不管是什么咖啡子类,不管数量有多少,迭代一遍就可以计算出价格,所以我觉得这个例子不是很有说服力。
[其他解释]
这么说吧
需要一个MilkIceCoffee对象,既有milk的特性,又有ice的特性
LZ要怎么使用list<coffer>来解决呢?
[其他解释]
head first设计模式里的装饰模式讲的很好,可以参考
[其他解释]
引用:
这么说吧
需要一个MilkIceCoffee对象,既有milk的特性,又有ice的特性
LZ要怎么使用list<coffer>来解决呢?


package decorator.guess;

public interface Coffee {


double cost();
}




package decorator.guess;

import java.util.List;

public class CalculatePrice {
public double cost(List<Coffee> beverage){
double d=0;
for(Coffee coffee:beverage){
d+=coffee.cost();
}

return d;
}
}


第二个例子计算任何种组合的coffe不都能计算出来吗
[其他解释]
引用:
这种需求,LZ用observe模式的思想确实可以很好的解决

coffee是基类,它拥有cost方法,这是coffee的基类方法
icecoffee继承coffee,它拥有加冰的方法addIce
milkcoffee继承coffee,它拥有加奶的方法addMilk
sugarcoffee继承coffee,它拥有加糖的方法addSugar

我现在想要一个对象,它具有icecoffee……

我在8楼不是说了吗,如果你想既有icecoffee和milkcoffee的特点,那么传一个Arrays.asList(new Coffee[]{icecoffee,milkcoffee})给cost方法不就行了吗

读书人网 >软件开发

热点推荐