装饰模式究竟有什么用?

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

为了便于说明,请参照http://www.jdon.com/designpatterns/decorator.htm,谢谢
...全文
277 13 打赏 收藏 转发到动态 举报
写回复
用AI写文章
13 条回复
切换为时间正序
请发表友善的回复…
发表回复
Erorr 2011-06-01
  • 打赏
  • 举报
回复
这个模式现实中用的好像不多,new来new去的也不是很优雅
zx8813443 2011-05-29
  • 打赏
  • 举报
回复
是的,可以保留原有行为的基础上添加一些行为
或者 替换原有的行为
truecn 2011-05-22
  • 打赏
  • 举报
回复
其实你的疑问是对的

因为这个模式偏向于是一个重构型模式。
theoffspring 2011-05-15
  • 打赏
  • 举报
回复
[Quote=引用 9 楼 yfkiss 的回复:]
这种需求,LZ用observe模式的思想确实可以很好的解决

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

我现在想要一个对象,它具有icecoffee……
[/Quote]
我在8楼不是说了吗,如果你想既有icecoffee和milkcoffee的特点,那么传一个Arrays.asList(new Coffee[]{icecoffee,milkcoffee})给cost方法不就行了吗
yfk 2011-05-11
  • 打赏
  • 举报
回复
这种需求,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先认真学习下




theoffspring 2011-05-10
  • 打赏
  • 举报
回复
[Quote=引用 6 楼 yfkiss 的回复:]
这么说吧
需要一个MilkIceCoffee对象,既有milk的特性,又有ice的特性
LZ要怎么使用list<coffer>来解决呢?
[/Quote]

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不都能计算出来吗
昵称很不好取 2011-05-10
  • 打赏
  • 举报
回复
head first设计模式里的装饰模式讲的很好,可以参考
yfk 2011-05-09
  • 打赏
  • 举报
回复
这么说吧
需要一个MilkIceCoffee对象,既有milk的特性,又有ice的特性
LZ要怎么使用list<coffer>来解决呢?
theoffspring 2011-05-09
  • 打赏
  • 举报
回复
[Quote=引用 4 楼 yfkiss 的回复:]
使用著名的coffer的例子可能好理解一点
下面这个case:
Coffee(咖啡)、MilkCoffee(加奶咖啡)、IceCoffee(加冰咖啡)、MilkIceCoffee(加冰和奶的咖啡)

使用继承,我们可能需要如下集成体系:
Coffee
Milkcoffee IceCoffee
MilkIceCoffee
如果组合数一多,就可能面……
[/Quote]
你这个例子我在head first design patterns里也看到了,不过我认为处理组合的时候,完全可以不定义新的类来实现,比如可以在一个方法中使用List<Coffee>作为参数,这样不管是什么咖啡子类,不管数量有多少,迭代一遍就可以计算出价格,所以我觉得这个例子不是很有说服力。
yfk 2011-05-09
  • 打赏
  • 举报
回复
使用著名的coffer的例子可能好理解一点
下面这个case:
Coffee(咖啡)、MilkCoffee(加奶咖啡)、IceCoffee(加冰咖啡)、MilkIceCoffee(加冰和奶的咖啡)

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

有一篇blog,LZ可以参考:http://blog.csdn.net/hivon/archive/2008/05/27/2485072.aspx
yfk 2011-05-09
  • 打赏
  • 举报
回复
抱歉,上面大了个不字。。。

以下两种情况适于使用decorate模式:
1. 可能有大量独立的扩展,为支持每一种组合将产生大量的子类,使得子类数目呈爆炸性增长(LZ提到的情况)
2. 因为类定义被隐藏,或类定义不能用于生成子类
yfk 2011-05-09
  • 打赏
  • 举报
回复
decorate模式理解为减少子类有问题~
事实上,decorate模式主要应用于解决如下问题:
1.在不影响其他对象的情况下,以动态、透明的方式给单个对象添加职责。
2.处理那些可以撤销的职责。

以下两种情况不适于使用decorate模式:
1. 可能有大量独立的扩展,为支持每一种组合将产生大量的子类,使得子类数目呈爆炸性增长(LZ提到的情况)
2. 因为类定义被隐藏,或类定义不能用于生成子类
ImN1 2011-05-08
  • 打赏
  • 举报
回复
装饰=装修+掩饰

C#设计模式(1) 一、 C# 面向对象程序设计复习 二、 设计模式举例 三、 先有鸡还是先有蛋? 四、 大瓶子套小瓶子还是小瓶子套大瓶子? 五、 .net本质 C#设计模式(2) 一、 "开放-封闭"原则(OCP) 二、 里氏代换原则(LSP) C#设计模式(3) 三、 依赖倒置原则(DIP) 四、 接口隔离原则(ISP) 五、 合成/聚合复用原则(CARP) 六、 迪米特法则(LoD) C#设计模式(4)-Simple Factory Pattern 一、 简单工厂(Simple Factory)模式 二、 Simple Factory模式角色与结构: 三、 程序举例: 四、 Simple Factory模式演化 五、 优点与缺点: C#设计模式(5)-Factory Method Pattern 一、 工厂方法(Factory Method)模式 二、 Factory Method模式角色与结构: 三、 程序举例: 四、 工厂方法模式与简单工厂模式 五、 Factory Method模式演化 六、 Factory Method模式与其它模式的关系 七、 另外一个例子 C#设计模式(6)-Abstract Factory Pattern 一、 抽象工厂(Abstract Factory)模式 二、 Abstract Factory模式的结构: 三、 程序举例: 四、 在什么情形下使用抽象工厂模式: 五、 抽象工厂的起源 六、 Abstract Factory模式在实际系统中的实现 七、 "开放-封闭"原则 C#设计模式(7)-Singleton Pattern 一、 单例(Singleton)模式 二、 Singleton模式的结构: 三、 程序举例: 四、 在什么情形下使用单例模式: 五、 Singleton模式在实际系统中的实现 六、 C#中的Singleton模式 C#设计模式(8)-Builder Pattern 一、 建造者(Builder)模式 二、 Builder模式的结构: 三、 程序举例: 四、 建造者模式的活动序列: 五、 建造者模式的实现: 六、 建造者模式的演化 七、 在什么情况下使用建造者模式 C#设计模式(9)-Prototype Pattern 一、 原型(Prototype)模式 二、 Prototype模式的结构: 三、 程序举例: 四、 带Prototype Manager的原型模式 五、 浅拷贝与深拷贝 六、 Prototype模式的优点与缺点 C#设计模式(10)-Adapter Pattern 一、 适配器(Adapter)模式 二、 类的Adapter模式的结构: 三、 类的Adapter模式示意性实现: 四、 对象的Adapter模式的结构: 五、 对象的Adapter模式示意性实现: 六、 在什么情况下使用适配器模式 七、 一个实际应用Adapter模式的例子 八、 关于Adapter模式的讨论 C#设计模式(11)-Composite Pattern 一、 合成(Composite)模式 二、 合成模式概述 三、 安全式的合成模式的结构 四、 安全式的合成模式实现 五、 透明式的合成模式结构 六、 透明式的合成模式实现 七、 使用合成模式时考虑的几个问题 八、 和尚的故事 九、 一个实际应用Composite模式的例子 C#设计模式(12)-Decorator Pattern 一、 装饰(Decorator)模式 二、 装饰模式的结构 三、 装饰模式示例性代码 四、 装饰模式应当在什么情况下使用 五、 装饰模式实际应用的例子 六、 使用装饰模式的优点和缺点 七、 模式实现的讨论 八、 透明性的要求 九、 装饰模式在.NET中的应用 C#设计模式(13)-Proxy Pattern 一、 代理(Proxy)模式 二、 代理的种类 三、 远程代理的例子 四、 代理模式的结构 五、 代理模式示例性代码 六、 高老庄悟空降八戒 七、 不同类型的代理模式 八、 代理模式实际应用的例子 设计模式(14)-Flyweight Pattern 一、 享元(Flyweight)模式 二、 单纯享元模式的结构 三、 单纯享元模式的示意性源代码 四、 复合享元模式的结构 五、 一个咖啡摊的例子 六、 咖啡屋的例子 七、 享元模式应当在什么情况下使用 八、 享元模式的优点和缺点 设计模式(15)-Facade Pattern 一、 门面(Facade)模式 二、 门面模式的结构 三、 门面模式的实现 四、 在什么情况下使用门面模式 五、 一个例子 六、 使用门面模式的设计 设计模式(16)-Bridge Pattern 一、 桥梁(Bridge)模式 二、 桥梁模式的结构 三、 桥梁模式的示意性源代码 四、 调制解调器问题 五、 另外一个实际应用Bridge模式的例子 六、 在什么情况下应当使用桥梁模式 设计模式(17)-Chain of Responsibility Pattern 一、 职责链(Chain of Responsibility)模式 二、 责任链模式的结构 三、 责任链模式的示意性源代码 四、 纯的与不纯的责任链模式 五、 责任链模式的实际应用案例 六、 责任链模式的实现 设计模式(18)-Command Pattern 一、 命令(Command)模式 二、 命令模式的结构 三、 命令模式的示意性源代码 四、 玉帝传美猴王上天 五、 命令模式的实现 六、 命令模式的实际应用案例 七、 在什么情况下应当使用命令模式 八、 使用命令模式的优点和缺点 设计模式(19)-Observer Pattern 一、 观察者(Observer)模式 二、 观察者模式的结构 三、 观察者模式的示意性源代码 四、 C#中的Delegate与Event 五、 一个实际应用观察者模式的例子 六、 观察者模式的优缺点 设计模式(20)-Visitor Pattern 一、 访问者(Visitor)模式 二、 访问者模式的结构 三、 示意性源代码 四、 一个实际应用Visitor模式的例子 五、 在什么情况下应当使用访问者模式 六、 使用访问者模式的优点和缺点 设计模式(21)-Template Method Pattern 一、 模板方法(Template Method)模式 二、 模版方法模式的结构 三、 模板方法模式的示意性代码 四、 继承作为复用的工具 五、 一个实际应用模板方法的例子 六、 模版方法模式中的方法 七、 重构的原则 设计模式(22)-Strategy Pattern 一、 策略(Strategy)模式 二、 策略模式的结构 三、 示意性源代码 四、 何时使用何种具体策略角色 五、 一个实际应用策略模式的例子 六、 在什么情况下应当使用策略模式 七、 策略模式的优点和缺点 八、 其它

3,405

社区成员

发帖
与我相关
我的任务
社区描述
专题开发/技术/项目 设计模式
社区管理员
  • 设计模式
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧