Don't think you are, know you are

博客园 首页 新随笔 管理


我觉得Decorator是比较透着灵气的设计模式,至于这句话怎么理解我也不好解释,呵呵,切入正题吧。

先看类图了:



注意到图中的一个环了吗,就是Decorator继承自Component,然后又引用Component的那个环路,就是它可以让我们不断动态的添加新的功能到Component 定义的一个对象。这也正是Decorator要解决的问题,为一个对象动态连接附加的职责。

 下面看代码:

假设一个SalesTicket类有一个打印功能,现在新的需求提出要增加打印一个台头和一个页脚,当然你可以用简单继承来实现,但是如果出现新的台头和页脚呢,如果需求还要求不同台头和页脚的组合,如果只是使用继承,你会发现多了一堆代码重复的“超生类”。
我们下面还是使用decorator模式来实现。

using System;
using System.Collections.Generic;
using System.Text;

namespace ConsoleApplication2
{
    class Program
    {
        static void Main(string[] args)
        {

            IComponent test = new Header1(new Header2(new Footer1 ((new SalesTicket()))));      //注意这里是组合,可以放在配置文件中,核在最后
            test.prtTicket();
            Console.ReadLine(); 
        }


    }

    public interface IComponent
    {
         void prtTicket();
    }

    public  class SalesTicket : IComponent                            // 这个是包装的核
    {
        void IComponent.prtTicket()
        {
            Console.WriteLine("Print Ticket Body"); 
        }      
    }

    public  class TicketDecorator : IComponent                  //与核为同一个接口
    {
        public  IComponent _myC;

          public TicketDecorator(IComponent myC)
        {
            _myC = myC;
        }
        public virtual void prtTicket()
        {
            if (_myC != null) _myC.prtTicket(); 
        }
    }

    public class Header1 : TicketDecorator
    {
        public Header1(IComponent myC):base(myC){}     //注意这里的写法。因为在派生类中,如果不使用 base 关键字来显式调用基类构造函数,则将隐式调用默认构造函数(如果有的话)。
        public override void prtTicket()
        {
            Console.WriteLine("Header1 Is Here");
            _myC.prtTicket();                                     //包装的是同名函数
        }
    }

    public class Header2 : TicketDecorator
    {
        public Header2(IComponent myC): base(myC) {}
        public override void prtTicket()
        {
            Console.WriteLine("Header2 Is Here");
            _myC.prtTicket(); 
        }        
    }

    public class Footer1 : TicketDecorator
    {
        public Footer1(IComponent myC): base(myC) {}
        public override void prtTicket()
        {
            _myC.prtTicket();
            Console.WriteLine("Footer1 Is Here");
        }     
    }
}
}

仔细看客户端代码,通过任意的组合我们实现不同的功能,这种组合可以无限的,因为大家接口都一样,可以套在一起,各司其职。

注意最后是以包装的核结尾的。

相比单独继承的好处,上面已经说了,灵活的组合显然好于僵硬的继承。

(还有什么要点明天总结,困了)



posted on 2007-07-20 00:53  炭炭  阅读(264)  评论(0编辑  收藏  举报