設計模式(7)---裝飾模式

1、定義:編程

裝飾模式(Decorator):動態地給一個對象添加一些額外的職責,就增長功能來講,裝飾模式比生成子類更爲靈活。架構

 簡單來講,裝飾模式很是相似於繼承,都能給對象添加一些額外的職責。若是須要靈活的添加一組有相對排列序列的功能,單純的繼承實現則顯得不是那麼優雅,裝飾模式能夠恰當的實現。ide

2、UML類圖:this

 

3、基本代碼spa

class Program
    {
        static void Main(string[] args)
        {
            ConcreteComponent c = new ConcreteComponent();
            ConcreteDecoratorA d1 = new ConcreteDecoratorA();
            ConcreteDecoratorB d2 = new ConcreteDecoratorB();

            d1.SetComponent(c);
            d2.SetComponent(d1);
            d2.Operation();

            Console.Read();
        }
    }

    abstract class Component
    {
        public abstract void Operation();
    }

    class ConcreteComponent : Component
    {
        public override void Operation()
        {
            Console.WriteLine("具體對象的操做");
        }
    }

    abstract class Decorator : Component
    {
        protected Component component;

        public void SetComponent(Component component)
        {
            this.component = component;
        }

        public override void Operation()
        {
            if (component != null)
            {
                component.Operation();
            }
        }
    }

    class ConcreteDecoratorA : Decorator
    {
        private string addState;

        public override void Operation()
        {
            base.Operation();
            addState = "new state";
            Console.WriteLine("具體裝飾對象A的操做");
        }
    }

    class ConcreteDecoratorB : Decorator
    {
        public override void Operation()
        {
            base.Operation();
            AddBehavior();
            Console.WriteLine("具體裝飾對象B的操做");
        }

        private void AddBehavior()
        {
            Console.WriteLine("B 的穿衣");
        }
    }
View Code

 

4、舉例說明設計

 在實際項目中,若是隻有一個ConcreteComponent類而沒有抽象的Component類,那麼Decorator類能夠是ConcreteComponent類的一個子類。一樣道理,若是隻有一個ConcreteDecorator類,那麼就沒有必要創建一個單獨的Decorator類,能夠把Decorator和ConcreteDecorator的責任合併成一個類。在下面實例中就是沒有抽象的Component類。實例的基本功能是完成一個穿衣功能:領帶垮褲大T恤的小菜。code

類圖:component

代碼:對象

class Program
    {
        static void Main(string[] args)
        {
            Person p = new Person("小菜");

            TShirts ts = new TShirts();
            BigTrouser bt = new BigTrouser();
            Tie ti = new Tie();

            ts.Decorate(p);
            bt.Decorate(ts);
            ti.Decorate(bt);
            ti.Show();

            Console.Read();
        }
    }

    class Person
    {
        public Person()
        { }

        private string name;
        public Person(string name)
        {
            this.name = name;
        }

        public virtual void Show()
        {
            Console.WriteLine("裝扮的{0}", name);
        }
    }

    class Finery : Person
    {
        protected Person component;

        public void Decorate(Person component)
        {
            this.component = component;
        }

        public override void Show()
        {
            if (component != null)
            {
                component.Show();
            }
        }
    }

    class TShirts : Finery
    {
        public override void Show()
        {
            //base.Show();
            Console.Write("大T恤");
            base.Show();
        }
    }

    class BigTrouser : Finery
    {
        public override void Show()
        {
            //base.Show();
            Console.Write("垮褲");
            base.Show();
        }
    }

    class Tie : Finery
    {
        public override void Show()
        {
            //base.Show();
            Console.Write("領帶");
            base.Show();
        }
    }
View Code

 

5、適用場景:blog

一、須要擴展一個類的功能,或給一個類添加附加指責。

二、須要動態的給一個對象添加功能,這些功能能夠再動態的撤銷。

三、須要增長由一些基本功能的排列組合而產生的很是大量的功能,從而使繼承關係變的不現實。

四、當不能採用生成子類的方法進行擴充時。一種狀況是,可能有大量獨立的擴展,爲支持每一種組合將產生大量的子類,使得子類數目呈爆炸性增加。另外一種狀況多是由於類定義被隱藏,或類定義不能用於生成子類。

 

6、優缺點:

優勢:

一、Decorator模式與繼承關係的目的都是要擴展對象的功能,可是Decorator能夠提供比繼承更多的靈活性。

二、經過使用不一樣的具體裝飾類以及這些裝飾類的排列組合,設計師能夠創造出不少不一樣行爲的組合。

缺點:

一、Decorator模式比繼承更加靈活機動的特性,也同時意味着更加多的複雜性。

二、Decorator模式會致使設計中出現許多小類,若是過分使用,會使程序變得很複雜。

三、Decorator模式是針對抽象組件(Component)類型編程。可是,若是你要針對具體組件編程時,就應該從新思考你的應用架構,以及裝飾者是否合適。固然也能夠改變Component接口,增長新的公開的行爲,實現「半透明」的裝飾者模式。在實際項目中要作出最佳選擇。

 

補充:

爲了更好的理解裝飾者模式,此處添加一個在網上看到一個感受很是不錯的實例:

class Program
    {
        static void Main(string[] args)
        {
            Phone phone = new ApplePhone();

            Sticker sticker = new Sticker();
            Accessories accessories = new Accessories();

            sticker.SetPhone(phone);
            accessories.SetPhone(sticker);
            accessories.Print();

            Console.Read();
        }
    }

    public abstract class Phone
    {
        public abstract void Print();
    }

    public class ApplePhone:Phone 
    {
        public override void Print()
        {
            Console.WriteLine("開始執行具體的對象-蘋果手機");
        }
    }

    public abstract class Decorator : Phone
    {
        private Phone phone;

        public void SetPhone(Phone phone)
        {
            this.phone = phone;
        }

        public override void Print()
        {
            if (phone != null)
            {
                phone.Print();
            }
        }
    }

    public class Sticker : Decorator
    {
        public override void Print()
        {
            base.Print();
            AddSticker();
        }

        public void AddSticker()
        {
            Console.WriteLine("蘋果手機貼膜");
        }
    }

    public class Accessories : Decorator
    {
        public override void Print()
        {
            base.Print();
            AddAccessories();
        }

        public void AddAccessories()
        {
            Console.WriteLine("蘋果手機掛件");
        }
    }
View Code

 結果以下:

相關文章
相關標籤/搜索