装饰(Decorator)模式

一、 装饰(Decorator)模式

  装饰(Decorator)模式又名包装(Wrapper)模式[GOF95]。装饰模式以对客户端透明的方式扩展对象的功能,是继承关系的一个替代方案。

二、 装饰模式的结构

  • 抽象构件(Component)角色:给出一个抽象接口,以规范准备接收附加责任的对象。
  • 具体构件(Concrete Component)角色:定义一个将要接收附加责任的类。
  • 装饰(Decorator)角色:持有一个构件(Component)对象的实例,并定义一个与抽象构件接口一致的接口。
  • 具体装饰(Concrete Decorator)角色:负责给构件对象"贴上"附加的责任

 

       /// <summary>
    ///  装饰(Decorator)模式
    ///  装饰(Decorator)模式又名包装(Wrapper)模式[GOF95]。
    ///  装饰模式以对客户端透明的方式扩展对象的功能,是继承关系的一个替代方案。
    /// </summary>
    class Program
    {
        static void Main(string[] args)
        {  
            // 创建的书和视频和显示
            Book book = new Book("巴金", "", 10);
            Video video = new Video("不详","扫毒", 23, 120);
            book.Display();
            video.Display();

            // 查看图书,然后借阅
            Console.WriteLine("\n查看图书,然后借阅:");

            Borrowable borrowvideo = new Borrowable(book);
            borrowvideo.BorrowItem("小三");
            borrowvideo.BorrowItem("小四"); 

            borrowvideo.Display(); 
            Console.ReadLine();
        }
    }


    /// <summary>
    /// 抽象构件(Component)角色
    /// </summary>
    public abstract class LibraryItem
    {
        // 字段
        private int numCopies;
        // 属性
        public int NumCopies
        {
            get { return numCopies; }
            set { numCopies = value; }
        }
        // 方法
        public abstract void Display();
    }

    /// <summary>
    /// 具体构件(Concrete Component)角色
    /// </summary>
    public class Book : LibraryItem
    {
        // 字段
        private string author;
        private string title;

        // 构造函数
        public Book(string author, string title, int numCopies)
        {
            this.author = author;
            this.title = title;
            this.NumCopies = numCopies;
        }

        // 函数
        public override void Display()
        {
            Console.WriteLine(" 书(Book) ------ ");
            Console.WriteLine(" 作者: {0}", author);
            Console.WriteLine(" 书名: {0}", title);
            Console.WriteLine(" # 副本: {0}", NumCopies);
        }
    }

    /// <summary>
    /// 具体构件(Concrete Component)角色
    /// </summary>
    public class Video : LibraryItem
    {
        // 字段
        private string director;
        private string title;
        private int playTime;

        // 构造函数
        public Video(string director, string title,int numCopies, int playTime)
        {
            this.director = director;
            this.title = title;
            this.NumCopies = numCopies;
            this.playTime = playTime;
        }

        // 方法
        public override void Display()
        {
            Console.WriteLine(" 视频(Video) ----- ");
            Console.WriteLine(" 导演: {0}", director);
            Console.WriteLine(" 片名: {0}", title);
            Console.WriteLine(" # 副本: {0}", NumCopies);
            Console.WriteLine(" 时长: {0} 分钟", playTime);
        }

    }

    /// <summary>
    /// 装饰(Decorator)角色
    /// </summary>
    public abstract class Decorator : LibraryItem
    {
        // 字段
        protected LibraryItem libraryItem;

        // 构造函数
        public Decorator(LibraryItem libraryItem)
        { this.libraryItem = libraryItem; }

        // 方法
        public override void Display()
        { libraryItem.Display(); }

    }

    /// <summary>
    /// 具体装饰(Concrete Decorator)角色
    /// </summary>
    public class Borrowable : Decorator
    {
        // 字段
        protected ArrayList borrowers = new ArrayList();

        // 构造函数
        public Borrowable(LibraryItem libraryItem)
            : base(libraryItem) { }

        // 方法
        public void BorrowItem(string name)
        {
            borrowers.Add(name);
            libraryItem.NumCopies--;
        }

        public void ReturnItem(string name)
        {
            borrowers.Remove(name);
            libraryItem.NumCopies++;
        }

        public override void Display()
        {
            base.Display();
            foreach (string borrower in borrowers)
                Console.WriteLine(" 借阅人: {0}", borrower);
        }
    }

三、 装饰模式应当在什么情况下使用

在以下情况下应当使用装饰模式:

  1. 需要扩展一个类的功能,或给一个类增加附加责任。
  2. 需要动态地给一个对象增加功能,这些功能可以再动态地撤销。
  3. 需要增加由一些基本功能的排列组合而产生的非常大量的功能,从而使继承关系变得不现实。

  4. 如果只有一个 具体构件(Concrete Component)角色 的时候 可以不要抽象构件(Component)角色

            //创建ConcreteComponent和两个修饰符
            ConcreteComponent c = new ConcreteComponent();
            ConcreteDecoratorA d1 = new ConcreteDecoratorA();
            ConcreteDecoratorB d2 = new ConcreteDecoratorB();

            // 链接修饰符
            d1.SetComponent(c);
            d2.SetComponent(d1);

            d2.Operation(); 

   /// <summary>
    /// 抽象构件(Component)角色
    /// </summary>
    public abstract class Component
    {
        // 方法
        public abstract void Operation();
    }
    // "具体构建"
    public class ConcreteComponent : Component
    {
        // 方法
        public override void Operation()
        {
            Console.WriteLine("具体对象的操作");
        }
    }
    // 装饰(Decorator)角色
    public abstract class Decorators : Component
    {
        // 字段
        protected Component component;
        // 方法
        public void SetComponent(Component component)
        {
            this.component = component;
        }
        public override void Operation()
        {
            if (component != null)
                component.Operation();
        }
    }

    // "具体装饰A"
    class ConcreteDecoratorA : Decorators
    {
        private string addedState;
        public override void Operation()
        {
            base.Operation();
            addedState = "new state";
            Console.WriteLine("具体装饰对象A的操作");
        }
    }

    // "具体装饰B"
    public class ConcreteDecoratorB : Decorators
    {
        public override void Operation()
        {
            base.Operation();
            AddedBehavior();
            Console.WriteLine("具体装饰对象B的操作");
        }
        void AddedBehavior()
        {
        }
    }
  
            Console.WriteLine("\n=========搭配衣服=============\n");

            Person xc = new Person("鸟人-安德森"); 
            TShirts tx = new TShirts();
            BigTrouser kk = new BigTrouser();

            tx.Decorate(xc);
            kk.Decorate(tx);
            kk.Show();


    /// <summary>
    /// 如果只有一个 具体构件(Concrete Component)角色 的时候 
    /// 可以不要抽象构件(Component)角色
    /// </summary>
    public class Person
    {
        public Person()
        { }
        private string name; 
        public Person(string name)
        {
            this.name = name;
        }
        public virtual void Show()
        {
            Console.WriteLine("装扮的{0}", name);
        }
    }
   
    ///装饰(Decorator)角色
    public class Finery : Person
    {
        protected Person component; 
        //打扮
        public void Decorate(Person component)
        {
            this.component = component;
        }
        public override void Show()
        {
            if (component != null)
                component.Show();
        }
    }

    /// <summary>
    /// 具体装饰
    /// </summary>
    public class TShirts : Finery
    {
        public override void Show()
        {
            Console.WriteLine("大T恤");
            base.Show();
        }
    }

    /// <summary>
    /// 具体装饰
    /// </summary>
    public class BigTrouser : Finery
    {
        public override void Show()
        {
            Console.WriteLine("大垮裤");
            base.Show();
        }
    }

 

posted @ 2014-04-25 15:54  dragon.net  阅读(224)  评论(0编辑  收藏  举报