裝飾者模式(wrapper):
允許向一個現有的物件添加新的功能,同時又不改變其結構,裝飾器模式是一種用于代替繼承的技術,無需通過繼承增加子類就能擴展物件的新功能,使用物件的關聯關系代替繼承關系,更加靈活,同時避免型別體系的快速膨脹,
示例:英雄學習技能
1 public class Program 2 { 3 private static void Main(string[] args) 4 { 5 //選擇英雄 6 Hero hero = new BlindMonk(); 7 Skills skills = new Skills(hero); 8 Skills r = new Skill_R(skills, "猛龍擺尾"); 9 Skills e = new Skill_E(r, "天雷破/摧筋斷骨"); 10 Skills w = new Skill_W(e, "金鐘罩/鐵布衫"); 11 Skills q = new Skill_Q(w, "天音波/回音擊"); 12 //學習技能 13 q.learnSkill(); 14 } 15 } 16 17 /// <summary> 18 /// Component 英雄介面 19 /// </summary> 20 public interface Hero 21 { 22 void learnSkill(); 23 } 24 25 /// <summary> 26 /// ConcreteComponent 具體英雄盲僧 27 /// </summary> 28 public class BlindMonk : Hero 29 { 30 public void learnSkill() 31 { 32 Console.WriteLine($"盲僧學習了以上技能!"); 33 } 34 } 35 36 /// <summary> 37 /// Decorator 技能欄 38 /// </summary> 39 public class Skills : Hero 40 { 41 private Hero hero; 42 43 public Skills(Hero hero) 44 { 45 this.hero = hero; 46 } 47 48 public virtual void learnSkill() 49 { 50 if (hero != null) 51 hero.learnSkill(); 52 } 53 } 54 55 /// <summary> 56 /// ConreteDecorator 技能:Q 57 /// </summary> 58 public class Skill_Q : Skills 59 { 60 private string _skillName; 61 62 public Skill_Q(Hero hero, string skillName) : base(hero) 63 { 64 this._skillName = skillName; 65 } 66 67 public override void learnSkill() 68 { 69 Console.WriteLine($"學習了技能Q:{this._skillName}"); 70 base.learnSkill(); 71 } 72 } 73 74 /// <summary> 75 /// ConreteDecorator 技能:W 76 /// </summary> 77 public class Skill_W : Skills 78 { 79 private string _skillName; 80 81 public Skill_W(Hero hero, string skillName) : base(hero) 82 { 83 this._skillName = skillName; 84 } 85 86 public override void learnSkill() 87 { 88 Console.WriteLine($"學習了技能W:{this._skillName}"); 89 base.learnSkill(); 90 } 91 } 92 93 /// <summary> 94 /// ConreteDecorator 技能:E 95 /// </summary> 96 public class Skill_E : Skills 97 { 98 private string _skillName; 99 100 public Skill_E(Hero hero, string skillName) : base(hero)101 {102 this._skillName = skillName;103 }104 105 public override void learnSkill()106 {107 Console.WriteLine($"學習了技能E:{this._skillName}");108 base.learnSkill();109 }110 }111 112 /// <summary>113 /// ConreteDecorator 技能:R114 /// </summary>115 public class Skill_R : Skills116 {117 private string _skillName;118 119 public Skill_R(Hero hero, string skillName) : base(hero)120 {121 this._skillName = skillName;122 }123 124 public override void learnSkill()125 {126 Console.WriteLine($"學習了技能R:{this._skillName}");127 base.learnSkill();128 }129 }
裝飾者模式有四個角色:
1)抽象構建(Component ):給出一個抽象介面,來規范被添加職責的物件;
2)具體構件(ConcreteComponent):定義一個將要接收附加責任的具體物件;
3)裝飾抽象類(Decorator):持有一個構件(Component)物件的實體,并定義一個與抽象構件介面一致的介面;
4)具體裝飾物件(ConreteDecorator):負責給構件物件 ”貼上“附加的責任,起到給Component添加職責的功能,
要點:
1)裝飾者和被裝飾物件有相同的超型別,
2)可以用一個或多個裝飾者包裝一個物件,
3)裝飾者可以在所委托被裝飾者的行為之前或之后,加上自己的行為,以達到特定的目的,
4)物件可以在任何時候被裝飾,所以可以在運行時動態的,不限量的用你喜歡的裝飾者來裝飾物件,
5)裝飾模式中使用繼承的關鍵是想達到裝飾者和被裝飾物件的型別匹配,而不是獲得其行為,
6)裝飾者一般對組件的客戶是透明的,除非客戶程式依賴于組件的具體型別,在實際專案中可以根據需要為裝飾者添加新的行為,做到“半透明”裝飾者,
.NET中裝飾者的使用:
MemoryStream memoryStream = new MemoryStream(new byte[] {95,96,97,98,99}); // 擴展緩沖的功能BufferedStream buffStream = new BufferedStream(memoryStream);// 添加加密的功能CryptoStream cryptoStream = new CryptoStream(memoryStream,new AesManaged().CreateEncryptor(),CryptoStreamMode.Write);// 添加壓縮功能GZipStream gzipStream = new GZipStream(memoryStream, CompressionMode.Compress, true);
裝飾者模式的優缺點:
優點:1)裝飾這模式和繼承的目的都是擴展物件的功能,但裝飾者模式比繼承更靈活;
2)通過使用不同的具體裝飾類以及這些類的排列組合,設計師可以創造出很多不同行為的組合;
3)裝飾者模式有很好地可擴展性
缺點:裝飾者模式會導致設計中出現許多小物件,如果過度使用,會讓程式變的更復雜,并且更多的物件會是的差錯變得困難,特別是這些物件看上去都很像,
裝飾者模式與代理模式的區別:
1)兩種模式的關注點不同,裝飾者模式關注的是在一個物件上動態的添加方法,而代理模式關注的是控制物件的訪問,
2)裝飾者模式可以讓使用者直觀的看到增強了哪些功能,而代理模式完全限制了使用者,只去呼叫代理,至于代理里面增加了什么功能,使用者是不知道,隱藏了一個物件的具體資訊,這正是為什么代理模式在初始化時不能像裝飾模式一樣傳入一個原始物件的引數的原因,
3)代理和真實物件之間的的關系通常在編譯時就已經確定了,而裝飾者能夠在運行時遞回地被構造,
參考:https://www.cnblogs.com/jaredlam/archive/2011/11/08/2241089.html
https://www.cnblogs.com/zhili/p/DecoratorPattern.html
https://blog.csdn.net/lxt610/article/details/81009089
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/44347.html
標籤:設計模式
上一篇:裝飾者模式,從吃黃燜雞開始說起
