1. <strong id="7actg"></strong>
    2. <table id="7actg"></table>

    3. <address id="7actg"></address>
      <address id="7actg"></address>
      1. <object id="7actg"><tt id="7actg"></tt></object>

        值得永久收藏的 C# 設計模式套路(二)

        共 8362字,需瀏覽 17分鐘

         ·

        2022-01-02 12:03

        設計模式套路,第二彈。

        ?

        在第一篇中,主要寫了創(chuàng)造模式相關的幾種套路。如果你是剛看到這個文章,建議你先去看看第一篇?傳送門。

        這一篇,我們說說結構模式相關的套路。

        結構模式,主要作用是將類型、對象和其它內容放在一起,以創(chuàng)建更大的結構,同時,又可以保持高度的靈活性和最佳性能。

        也是像上一篇一樣,一個一個來說。

        一、適配器模式

        適配器這個名字非常好理解,就像我們充電器的插頭,是用來協(xié)調兩個不同的東東之間的通信,并讓他們互相理解。

        代碼也很簡單:

        public?class?AnotherType
        {

        ????public?string?GetAuthorInfo()
        ????
        {
        ????????return?"I?am?WangPlus";
        ????}
        }
        public?interface?IAdapter
        {
        ????string?GetInfo();
        }
        public?class?Adapter?:?IAdapter
        {
        ????private?readonly?AnotherType?_anotherType;
        ????public?Adapter(AnotherType?anotherType)
        ????
        {
        ????????_anotherType?=?anotherType;
        ????}
        ????public?string?GetInfo()
        ????
        {
        ????????return?_anotherType.GetAuthorInfo();
        ????}
        }
        public?class?Example
        {

        ????public?void?Test()
        ????
        {
        ????????var?adapter?=?new?Adapter(new?AnotherType());
        ????????Console.WriteLine(adapter.GetInfo());
        ????}
        ????//?result:
        ????//?I?am?WangPlus
        }

        沒想到吧?這樣的代碼經常寫,居然也是個模式。所以呀,還是我上一篇提到的說法:先有內容,然后才有概念和標準。套路一直在,只是很多人不知道他叫什么。

        二、橋模式

        這個也好理解,就是在兩個東西之間搭了一個橋。

        正常使用時,是把實體類與接口和抽象分離開。有一個非常明顯的好處,是幾個實現(xiàn)可以使用不同的技術。

        理解概念有點難,還是看代碼:

        public?interface?IBridgeType
        {
        ????void?GetInfo();
        }
        public?class?BridgeA?:?IBridgeType
        {
        ????public?void?GetInfo()
        ????
        {
        ????????Console.WriteLine("I?am?WangPlus");
        ????}
        }
        public?class?BridgeB?:?IBridgeType
        {
        ????public?void?GetInfo()
        ????
        {
        ????????Console.WriteLine("I?am?another?WangPlus");
        ????}
        }
        public?interface?IBridge
        {
        ????public?IBridgeType?bridgeType
        ????{
        ????????get;
        ????????set;
        ????}
        ????void?GetInfo();
        }
        public?class?BridgeType?:?IBridge
        {
        ????public?IBridgeType?bridgeType
        ????{
        ????????get;
        ????????set;
        ????}
        ????public?void?GetInfo()
        ????
        {
        ????????bridgeType.GetInfo();
        ????}
        }
        public?static?class?BridgeExample
        {

        ????public?static?void?Test()
        ????
        {
        ????????var?bridgeType?=?new?BridgeType();
        ????????bridgeType.bridgeType?=?new?BridgeA();
        ????????bridgeType.GetInfo();
        ????????bridgeType.bridgeType?=?new?BridgeB();
        ????????bridgeType.GetInfo();
        ????}
        ????//?result:
        ????//?I?am?WangPlus
        ????//?I?am?another?WangPlus
        }

        BridgeA 和 BridgeA 是兩個實現(xiàn),這兒就是上面說的不同的技術,用不同的技術實現(xiàn)了同一個接口。然后通過 IBridge 橋接到一個實現(xiàn)中。

        使用時,使用不同的實現(xiàn),但用相同的結構進行調用。在有需要時,我們可以根據場景做出無數(shù)個 BridgeN ,來實現(xiàn)黑盒類似但白盒完全不同的實體。

        三、復合模式

        聽著就大就復雜。沒錯,所有叫復合的東西,都會形成一個樹狀結構。這好像是編程中的一個默認約定?

        復合設計模式,就是把對象放在一個更大的樹狀結構的對象中,以多層次結構來呈現(xiàn)對象,以統(tǒng)一方式處理對象。

        看看這個復雜代碼的套路:

        public?abstract?class?Mobile
        {

        ????protected?string?Name;
        ????protected?Mobile(string?name)
        ????
        {
        ????????Name?=?name;
        ????}
        ????public?virtual?void?Add(Mobile?mobile)
        ????
        {
        ????????throw?new?NotImplementedException();
        ????}
        ????public?virtual?void?GetTree(int?indent)
        ????
        {
        ????????throw?new?NotImplementedException();
        ????}
        }
        public?class?MobileMemory?:?Mobile
        {
        ????public?MobileMemory(string?name)?:?base(name)?{?}
        ????public?override?void?GetTree(int?indent)
        ????
        {
        ????????Console.WriteLine(new?String('-',?indent)?+?"?"?+?Name);
        ????}
        }
        public?class?MobileModel?:?Mobile
        {
        ????private?readonly?List?_mobiles?=?new?List();
        ????public?MobileModel(string?name)?:?base(name)?{?}
        ????public?override?void?Add(Mobile?mobile)
        ????
        {
        ????????_mobiles.Add(mobile);
        ????}
        ????public?override?void?GetTree(int?indent)
        ????
        {
        ????????Console.WriteLine(new?String('-',?indent)?+?"+?"?+?Name);

        ????????foreach?(var?mobile?in?_mobiles)
        ????????{
        ????????????mobile.GetTree(indent?+?2);
        ????????}
        ????}
        }
        public?static?class?Example
        {

        ????public?static?void?Test()
        ????
        {
        ????????var?brand?=?new?MobileModel("IPhone");

        ????????var?model13?=?new?MobileModel("13Pro");
        ????????var?model12?=?new?MobileModel("12Pro");

        ????????var?memory512G?=?new?MobileMemory("512G");
        ????????var?memory256G?=?new?MobileMemory("256G");

        ????????model13.Add(memory256G);
        ????????model13.Add(memory512G);

        ????????model12.Add(memory256G);
        ????????model12.Add(memory512G);

        ????????brand.Add(model12);
        ????????brand.Add(model13);

        ????????brand.GetTree(1);
        ????}
        ????//?result:
        ????//?---+?12Pro
        ????//?-----?256G
        ????//?-----?512G
        ????//?---+?13Pro
        ????//?-----?256G
        ????//?-----?512G
        }

        這個套路確實稍微有點復雜。補充解釋一下:

        • MobileMemory 和 MobileModel,是為了表現(xiàn)多種對象,沒有特殊含義,里面的區(qū)別就是 GetTree() 里打印出來的字符不同。

        • 需要清楚理解的部分是 MobileModel 里構建的 _mobiles,他是一個頂層抽象類的數(shù)組。

        • 這個模式最重要的結構,是用抽象類去組織數(shù)據,用實體類去操作功能。

        另外,如果你的開發(fā)功力夠,在這個架構中,實體本身也可以是復合對象。

        四、裝飾模式

        這也是一個常用的模式。通過對抽象或接口的擴展,來加入對象功能。

        而且這個套路的代碼特別好理解:

        public?interface?IMobile
        {
        ????public?string?Brand
        ????{
        ????????get;
        ????}
        ????public?string?Model
        ????{
        ????????get;
        ????}
        ????public?abstract?void?GetInfo();
        }
        public?class?IPhone?:?IMobile
        {
        ????public?string?Brand?=>?"Apple";
        ????public?string?Model?=>?"13Pro";
        ????public?void?GetInfo()
        ????
        {
        ????????Console.WriteLine(this.ToJson());
        ????}
        }
        public?class?IPhoneWithMemory?:?IMobile
        {
        ????private?readonly?IMobile?_mobile;
        ????public?IPhoneWithMemory(IMobile?mobile)
        ????
        {
        ????????_mobile?=?mobile;
        ????}

        ????public?string?Brand?=>?"Apple";
        ????public?string?Model?=>?"13Pro";
        ????public?string?Memory?=>?"512G";
        ????public?void?GetInfo()
        ????
        {
        ????????Console.WriteLine(this.ToJson());
        ????}
        }
        public?static?class?Example
        {

        ????public?static?void?Test()
        ????
        {
        ????????var?iphone?=?new?IPhone();
        ????????iphone.GetInfo();
        ????????var?iphoneWithMemory?=?new?IPhoneWithMemory(iphone);
        ????????iphoneWithMemory.GetInfo();
        ????}
        ????//?result:
        ????//?{"Brand":"Apple","Model":"13Pro"}
        ????//?{"Brand":"Apple","Model":"13Pro","Memory":"512G"}
        }

        從上邊的 IMobile 接口開始,每一個實體都是對前一個實體的補充和完善。

        這種寫法,在團隊項目中很常見,可以在確保不對別人的內容進行修改的基礎上,擴展新的功能。不用改別人的代碼,又能補充進去新的內容。有沒有被爽到?

        五、外觀模式

        這個模式名稱起得不知所云。不過意思和代碼倒是很簡單,就是把其它的接口、類、框架等的復雜系統(tǒng)匯集起來,讓人能簡單使用。

        代碼一看就懂:

        public?class?Facade
        {

        ????private?readonly?Mobile?_mobile;
        ????private?readonly?Laptop?_laptop;
        ????public?Facade(Mobile?mobile,?Laptop?laptop)
        ????
        {
        ????????_mobile?=?mobile;
        ????????_laptop?=?laptop;
        ????}
        ????public?void?GetInfo()
        ????
        {
        ????????_mobile.GetInfo();
        ????????_laptop.GetInfo();
        ????}
        }
        public?class?Mobile
        {

        ????public?void?GetInfo()
        ????
        {
        ????????Console.WriteLine("I?am?mobile");
        ????}
        }
        public?class?Laptop
        {

        ????public?void?GetInfo()
        ????
        {
        ????????Console.WriteLine("I?am?laptop");
        ????}
        }
        public?static?class?Example
        {

        ????public?static?void?Test()
        ????
        {
        ????????var?mobile?=?new?Mobile();
        ????????var?laptop?=?new?Laptop();
        ????????var?facade?=?new?Facade(mobile,?laptop);
        ????????facade.GetInfo();
        ????}
        ????//?result:
        ????//?I?am?mobile
        ????//?I?am?laptop
        }

        這個模式,在開發(fā)中也用得比較多。尤其在團隊項目中,會經常用到,原因跟上面一樣。

        六、輕量級模式

        嗯,就是輕的意思。這個輕,不是寫的少,而是內存使用少。

        所以這個模式的主要優(yōu)勢,就是節(jié)省內存。

        這個模式沒辦法給出簡單的套路。他本身是一種想法,是一種寫在代碼中的思想,而不是一個套路性的代碼組。

        我拿一段代碼來說明一下:

        public?class?Flyweight
        {

        ????private?readonly?Liststring,?DemoClass>>?_sharedObjects?=?new();
        ????public?Flyweight()
        ????
        {
        ????????_sharedObjects.Add(new?KeyValuePair<string,?DemoClass>("A",?new?DemoClass()));
        ????????_sharedObjects.Add(new?KeyValuePair<string,?DemoClass>("B",?new?DemoClass()));
        ????}
        ????public?DemoClass?GetObject(string?key)
        ????
        {
        ????????return?_sharedObjects.SingleOrDefault(c?=>?c.Key?==?key).Value;
        ????}
        }
        public?interface?IDemoClass
        {
        ????public?void?Operation(string?name);
        }
        public?class?DemoClass?:?IDemoClass
        {
        ????public?void?Operation(string?name)
        ????
        {
        ????????Console.WriteLine(name);
        ????}
        }
        public?static?class?Example
        {

        ????public?static?void?Test()
        ????
        {
        ????????var?flyweight?=?new?Flyweight();
        ????????flyweight.GetObject("A").Operation("Hello");
        ????????flyweight.GetObject("B").Operation("I?am?WangPlus");

        ????????var?heavy?=?new?DemoClass();
        ????????heavy.Operation("Hello,?I?am?WangPlus");
        ????}
        ????//?result:
        ????//?下面是輕量級模式
        ????//?Hello
        ????//?I?am?WangPlus
        ????//?下面是普通模式
        ????//?Hello,?I?am?WangPlus
        }

        在這段代碼里,真正屬于輕量級模式模式的其實只是里面的這一段:

        ????private?readonly?Liststring,?DemoClass>>?_sharedObjects?=?new();
        ????public?Flyweight()
        ????
        {
        ????????_sharedObjects.Add(new?KeyValuePair<string,?DemoClass>("A",?new?DemoClass()));
        ????????_sharedObjects.Add(new?KeyValuePair<string,?DemoClass>("B",?new?DemoClass()));
        ????}

        能理解嗎?這一段主要是構造了一個集合,用來存放對象。后面調用對象時,是從這個集合里出來的。

        這樣寫的好處,是如果對象很多,每次 new 會占用大量內存,而先期存儲在一個集合中,會讓這個內存占用變得小很多。

        好吧,如果不理解,也沒關系。在 Dotnet 的整個源碼中,這樣使用的也并不多。

        所以這個模式屬于一個可以意會的模式。而且事實上,現(xiàn)在的內存成本之低,已經很少需要這么費心了。

        七、代理模式

        這個模式也好理解,就是加了一個代理。通過中間類型來控制對于主類型的訪問。

        嗯,別擔心,這個是有套路的。

        public?abstract?class?MainAbst
        {

        ????public?abstract?void?GetInfo();
        }
        public?class?MainClass?:?MainAbst
        {
        ????public?override?void?GetInfo()
        ????
        {
        ????????Console.WriteLine("I?am?WangPlus");
        ????}
        }
        public?class?Proxy?:?MainAbst
        {
        ????private?MainClass?_main;
        ????public?Proxy(MainClass?main)
        ????
        {
        ????????_main?=?main;
        ????}
        ????public?override?void?GetInfo()
        ????
        {
        ????????_main????=?new?MainClass();
        ????????_main.GetInfo();
        ????}
        }
        public?static?class?ProxyExample
        {

        ????public?static?void?Test()
        ????
        {
        ????????var?proxy?=?new?Proxy(new?MainClass());
        ????????proxy.GetInfo();
        ????}
        ????//?result:
        ????//?I?am?WangPlus
        }

        這個套路也容易懂。MainClass 是我們的主類,在執(zhí)行一些特定的方法。加出了一個代理類 Proxy。外部調用時,通過 Proxy 來調用主類的方法,同時,如果有需要對主類的輸入輸出進行處理,可以在 Proxy 的方法里直接寫。

        又是一個團隊協(xié)作會用到的模式,嘿嘿。

        ?

        結構模式的套路就是這樣了。

        還有一類模式,是行為設計模式。咱們改天再寫。

        喜歡就來個三連,讓更多人因你而受益


        瀏覽 46
        點贊
        評論
        收藏
        分享

        手機掃一掃分享

        分享
        舉報
        評論
        圖片
        表情
        推薦
        點贊
        評論
        收藏
        分享

        手機掃一掃分享

        分享
        舉報
        1. <strong id="7actg"></strong>
        2. <table id="7actg"></table>

        3. <address id="7actg"></address>
          <address id="7actg"></address>
          1. <object id="7actg"><tt id="7actg"></tt></object>
            操一操亚洲色 | 国产精品露奶操逼 | 亚洲色天 | 亚洲一级a免费在线观看 | 成人无码HAV在线看免费 | 性一交一乱一乱一 | 激情五月乱伦网 | 91肏屄 | 午夜主播福利 | 蜜臀精品色无码蜜臀AV |