论坛首页 Java版 设计模式

设计模式笔记:好玩的Decorator模式

浏览 3783 次
精华帖 (0) :: 良好帖 (5) :: 新手帖 (0) :: 隐藏帖 (0)
作者 正文
最后更新时间:2007-12-05 关键字: 好玩的decorator模式
《设计模式》对Decorator的描述:动态给一个对象添加一些额外职责。就添加功能来说,Decorator模式比生成子类更灵活。

Decorator让我感觉设计者非常聪明,这是个好有趣聪慧的模式,马上看例子:


1.不使用Decorator模式的设计:

a.需求:打印正文

java 代码
  1. public class Ticket{
  2. public void prtTicket(){
  3. System.out.println("Sales Ticket");
  4. }
  5. }


b.需求改变:打印正文前,先打印Header
java 代码
  1. public class Ticket{
  2. public void prtTicket(){
  3. System.out.println("Header");
  4. System.out.println("Sales Ticket");
  5. }
  6. }

c.需求再度改变:正文后打印Footer
java 代码
  1. public class Ticket{
  2. public void prtTicket(){
  3. System.out.println("Header");
  4. System.out.println("Sales Ticket");
  5. System.out.println("Footer");
  6. }
  7. }


2.使用Decorator后的设计:

java 代码
  1. abstract public class Component{
  2. abstract public void prtTicket();
  3. }
  4. abstract public class TicketDecorator extend Component {
  5. private Component myTrailer;
  6. public TicketDecorator(Component comp){
  7. myTrailer = comp;
  8. }
  9. public void callTrailer(){
  10. if(myTrailer != null)
  11. myTrailer.prtTicket();
  12. }
  13. }
  14. public class SaleTicket extend Component{
  15. public void prtTicket(){
  16. System.out.println("Sale Ticket");
  17. }
  18. }
  19. public class Header extend TicketDecorator{
  20. public Header(Component comp){
  21. super(comp);
  22. }
  23. public void prtTicket(){
  24. System.out.println("Header");
  25. super.callTrailer();
  26. }
  27. }
  28. public class Footer extend TicketDecorator{
  29. public Footer (Component comp){
  30. super(comp);
  31. }
  32. public void prtTicket(){
  33. super.callTrailer();
  34. System.out.println("Footer");
  35. }
  36. }
  37. public class Test{
  38. public static void main(String args[]){
  39. Component c = new Header(new Footer(new SaleTicket()));
  40. c.prtTicket();
  41. }
  42. }

于是,无论添加多少个功能,每个Decorator都之关心自己的功能,我们能任意重排Decorator的顺序,无需改变任何代码。

在java io中用到了Decorator模式。
   
最后更新时间:2008-02-19
只谈到是什么,没谈到为什么!
   
0 请登录后投票
最后更新时间:2008-02-19
细细看了一下Header类和Footer类中其实现方法中的步骤是不一样的,这顺序不还是不能改的吗? 望解答。
   
0 请登录后投票
最后更新时间:2008-02-19
方案2的代码可读性,效率,可维护性都比不上方案1啊,呵呵。。。
方案1简直就是神来之笔,简单,易读,高效,利于维护。
其实lz这个例子可以用来作为使用design pattern的一个反例,就是不用什么都用design pattern,需要用才用,用比不用好才用,不要过度设计。如果可以1+1=2得来的东西,就不要通过1+2-4+2+1=2来得到。
不合算,不值得,是对资源(精力,时间)的浪费。
胡乱说两句。
   
0 请登录后投票
最后更新时间:2008-02-20
xiaolin0105 写道
方案2的代码可读性,效率,可维护性都比不上方案1啊,呵呵。。。
方案1简直就是神来之笔,简单,易读,高效,利于维护。
其实lz这个例子可以用来作为使用design pattern的一个反例,就是不用什么都用design pattern,需要用才用,用比不用好才用,不要过度设计。如果可以1+1=2得来的东西,就不要通过1+2-4+2+1=2来得到。
不合算,不值得,是对资源(精力,时间)的浪费。
胡乱说两句。

我想楼主的意思应该是用最简单的方法来说明decorator模式,但是对于一上来二话不说先贴代码,然后总结下结束,让我有点摸不到头脑,decorator模式到底有趣到哪了,为什么要用这种模式。

PS:讲设计模式只要类图就可以了,关键是思想。
   
0 请登录后投票
最后更新时间:2008-02-21
呵呵,是吗。
当我从设计模式读到这文的时候,感觉非常开心,设计者把代码写灵活了。原来代码还能这么写。

方案1如果要修改,则需要修改Ticket的源代码。
方案1模拟了业务变更的流程。全部需要修改Ticket源代码。

方案2面对变更的需求,不用改Ticket,使用者自己按需求构造即可。
方案2如果要修改,不用修改源代码,添加一个自己的类(即修饰者)即可。
   
0 请登录后投票
最后更新时间:2008-02-21
引用
细细看了一下Header类和Footer类中其实现方法中的步骤是不一样的,这顺序不还是不能改的吗? 望解答。


header顾名思义应该是头部。
footer顾名思义在尾部。

当然可以header + header + header达到改变顺序
footer + footer + footer.

你的意思是不可能出现:
header - footer - header -footer
这当然不能出现了。
   
0 请登录后投票
最后更新时间:2008-02-21
yongyuan.jiang 写道
呵呵,是吗。
当我从设计模式读到这文的时候,感觉非常开心,设计者把代码写灵活了。原来代码还能这么写。

方案1如果要修改,则需要修改Ticket的源代码。
方案1模拟了业务变更的流程。全部需要修改Ticket源代码。

方案2面对变更的需求,不用改Ticket,使用者自己按需求构造即可。
方案2如果要修改,不用修改源代码,添加一个自己的类(即修饰者)即可。


对呀,对呀。还要加上ResourceBundle:万一需求变化需要国际化的嘛;
还要注射PrintStream而不是直接System.out:万一需求变化要写到文件中的嘛;
还要加一个策略模式:万一需求变化不是写纯文本而是html甚至flash的嘛;
还要加一个observer模式:万一需求变化要响应不同的组件打印事件的嘛;
还要搞一个xml文件来组装所有组件的嘛;还要弄一个controller, view, model来分隔不同层次的逻辑的嘛;
还要用上aop:万一需求变化那啥那啥的嘛。。。

啥叫”架构师“?就是所有能叫得上名的模式你全给他整上。
   
0 请登录后投票
最后更新时间:2008-02-21
java的io用的就是这个模式
 
只能说解决了java不能多继承的问题 但在执行顺序上不灵活
   
0 请登录后投票
最后更新时间:2008-02-21
其实我觉得比这更好的办法是用内部类来实现
只是可能会在代码的观赏性上没这个好
   
0 请登录后投票
论坛首页 Java版 设计模式

跳转论坛:
JavaEye推荐