張江男:指聚集在上海張江高科技園區,具備理工科背景,常常深居簡出,工作勤奮,拙於表達。他們薪水很高,卻不太會消費;他們有自己特有的浪漫,卻難以招女孩喜歡;他們智商很高,卻普遍想法簡單。 他們被武斷地概念化為“張江男”。 專家說,他們是一群不懂生活的“廢棄生命”;老人們說,他們是可靠的結婚對象;女孩們說,他們更喜歡看電腦而不是看我;而這群被冠以“張江難”的年輕人卻說:我們並不寂寞,也很浪漫。
張江女,現於張江某IT公司工作,工作時一頭長發無時間打理,黑框眼鏡下是長時間對著電腦而導致的近視眼,右手手機左手雜糧煎餅,深色的大衣和干練的牛仔再配上白色的舒適平底鞋,神魂好似已經雲游天際之外,這俨然就是現在的張江女們上班標准匹配。
不要嘲笑他們,他們是程序員,他們為工作在默默的付出,他們心酸的背後有豐厚的回報。
張江男一般26歲就月薪稅後1w,30歲就至少2w+了,牛逼的35歲的時候基本年薪50萬或者100萬了,他們就是這麼吊的一群人。
其實張江男、張江女的形象就是我們大眾程序的寫照,但是我們有他們的標配打扮,沒有他們客觀的收入,這是我們在讀的程序員值得反思的地方。
說了這麼多也該回歸點正題了,今天我們就說說設計模式中的裝飾模式。
裝飾模式(Decorator Pattern) :動態地給一個對象增加一些額外的職責(Responsibility),就增加對象功能來說,裝飾模式比生成子類實現更為靈活。
裝飾模式以對客戶透明的方式動態地給一個對象附加上更多的責任,換言之,客戶端並不會覺得對象在裝飾前和裝飾後有什麼不同。裝飾模式可以在不需要創造更多子類的情況下,將對象的功能加以擴展。這就是裝飾模式的模式動機。
裝飾模式包括四個角色:
抽象構件角色(Component):定義一個抽象接口,用以給這些對象動態地添加職責。
具體構件角色(ConcreteComponent):定義一個具體的對象,也可以給這個對象添加一些職責。
裝飾類角色(Decorator): 裝飾抽象類,繼承了Component,從外類來擴展Component類的功能。
具體裝飾者角色(ConcretorDecorator):負責給構建對象添加職責。
根據四個角色做出具體代碼:
// 抽象構件 public abstract class Component { public abstract void Opration(); } // 具體構件 public class ConcreteComponent : Component { public override void Opration() { Console.WriteLine("具體構件的基本操作"); } } /// <summary> /// 抽象的裝飾類,它不能初始化對象。 /// </summary> public abstract class Decorator : Component { protected Component Component; public void SetComponent(Component component) { this.Component = component; } /// <summary> /// 重寫Operation,實際執行的是Component的Operation。 /// </summary> public override void Opration() { if (Component != null) { Component.Opration(); } } } //具體裝飾類A public class ConcreteDecoratorA : Decorator { private void SpecialOpration() { Console.WriteLine("A的操作"); } public override void Opration() { base.Opration(); this.SpecialOpration(); } } //具體裝飾類B public class ConcreteDecoratorB : Decorator { private void SpecialOprationA() { Console.WriteLine("B的A操作"); } private void SpecialOprationB() { Console.WriteLine("B的B操作"); } public override void Opration() { base.Opration(); this.SpecialOprationA(); this.SpecialOprationB(); } } static void Main(string[] args) { //定義構件 ConcreteComponent concreteComponent = new ConcreteComponent(); //定義具體裝飾類 ConcreteDecoratorA a = new ConcreteDecoratorA(); ConcreteDecoratorB b = new ConcreteDecoratorB(); //把AB的操作交給構件 a.SetComponent(concreteComponent); b.SetComponent(a); //構件除了自己的基本操作,還具有A的操作、B的操作,最終執行b.Opration(); b.Opration(); Console.ReadKey(); }
運行結果:
很容易理解,就是增加一個修飾類包裹原來的類,包裹的方式一般是通過在將原來的對象作為修飾類的構造函數的參數。裝飾類實現新的功能,但是,在不需要用到新功能的地方,它可以直接調用原來的類中的方法。修飾類必須和原來的類有相同的接口。
開頭說了那麼多張江男和張江女的事情,我們就依照這個實例寫個代碼:
//抽象人 public abstract class Person { public abstract void Show(); } //張江男 public class ZhangJiangItMan : Person { public override void Show() { Console.WriteLine("只穿了基本必要裝扮!"); } } //張江女 public class ZhangJiangItWoMan : Person { public override void Show() { Console.WriteLine("只穿了基本必要裝扮!"); } } //穿著打扮 public abstract class Dress : Person { protected Person Person; //開始裝扮 public void SetDress(Person person) { this.Person = person; } public override void Show() { if (Person != null) { Person.Show(); } } } //具體服裝打扮 public class Backpack : Dress { public override void Show() { base.Show(); Console.WriteLine("張江男必備雙肩包!"); } } //眼鏡 public class Glasses : Dress { public override void Show() { base.Show(); Console.WriteLine("張江男張江女必備黑框眼鏡!"); } } //萬能搭配的襯衫 public class Shirt : Dress { public override void Show() { base.Show(); Console.WriteLine("張江男張江女必備萬能搭配的襯衫!"); } } //萬能搭配的牛仔褲 public class Jeans : Dress { public override void Show() { base.Show(); Console.WriteLine("張江男張江女必備萬能搭配的牛仔褲!"); } } static void Main(string[] args) { //實例化服飾 Backpack backpack = new Backpack(); Glasses glasses = new Glasses(); Shirt shirt = new Shirt(); Jeans jeans = new Jeans(); //實例化張江男 ZhangJiangItMan zhangJiangItMan = new ZhangJiangItMan(); //開始裝扮 backpack.SetDress(zhangJiangItMan); glasses.SetDress(backpack); shirt.SetDress(glasses); jeans.SetDress(shirt); //輸出張江男裝扮 jeans.Show(); //實例化張江女 ZhangJiangItWoMan zhangJiangItWoMan = new ZhangJiangItWoMan(); backpack.SetDress(zhangJiangItWoMan); glasses.SetDress(backpack); shirt.SetDress(glasses); jeans.SetDress(shirt); //輸出張江女裝扮 jeans.Show(); Console.ReadKey(); }
運行結果:
就這麼簡單,就這麼好理解
優點:
裝飾模式與繼承關系的目的都是要擴展對象的功能,但是裝飾模式可以提供比繼承更多的靈活性。
可以通過一種動態的方式來擴展一個對象的功能,通過配置文件可以在運行時選擇不同的裝飾器,從而實現不同的行為。
通過使用不同的具體裝飾類以及這些裝飾類的排列組合,可以創造出很多不同行為的組合。可以使用多個具體裝飾類來裝飾同一對象,得到功能更為強大的對象。
缺點:
這種比繼承更加靈活機動的特性,也同時意味著裝飾模式比繼承更加易於出錯,排錯也很困難,對於多次裝飾的對象,調試時尋找錯誤可能需要逐級排查,較為煩瑣。
代碼下載:https://yunpan.cn/cYpIGJCDwNqce (提取碼:9e33)