機構類型設計模式目錄,以前的建立類型的設計模式介紹看這裏html
1. 適配器模式(將某個類的接口轉換成客戶端指望的另外一個接口表示。適配器模式能夠消除因爲接口不匹配所形成的類兼容性問題。)引用院子Learning hard的示例,比較經典的插頭例子數據庫
using System; /// 這裏以插座和插頭的例子來詮釋適配器模式 /// 如今咱們買的電器插頭是2個孔,可是咱們買的插座只有3個孔的 /// 這是咱們想把電器插在插座上的話就須要一個電適配器 namespace 設計模式之適配器模式 { /// <summary> /// 客戶端,客戶想要把2個孔的插頭 轉變成三個孔的插頭,這個轉變交給適配器就好 /// 既然適配器須要完成這個功能,因此它必須同時具體2個孔插頭和三個孔插頭的特徵 /// </summary> class Client { static void Main(string[] args) { // 如今客戶端能夠經過電適配要使用2個孔的插頭了 IThreeHole threehole = new PowerAdapter(); threehole.Request(); Console.ReadLine(); } } /// <summary> /// 三個孔的插頭,也就是適配器模式中的目標角色 /// </summary> public interface IThreeHole { void Request(); } /// <summary> /// 兩個孔的插頭,源角色——須要適配的類 /// </summary> public abstract class TwoHole { public void SpecificRequest() { Console.WriteLine("我是兩個孔的插頭"); } } /// <summary> /// 適配器類,接口要放在類的後面 /// 適配器類提供了三個孔插頭的行爲,但其本質是調用兩個孔插頭的方法 /// </summary> public class PowerAdapter:TwoHole,IThreeHole { /// <summary> /// 實現三個孔插頭接口方法 /// </summary> public void Request() { // 調用兩個孔插頭方法 this.SpecificRequest(); } } }
2. 橋接模式(將一個抽象與實現解耦,以便二者能夠獨立的變化。)我看到原有有舉例使用在數據庫訪問層面上,將不一樣數據庫橋接到抽象的操做類,是個很是好的應用。設計模式
//抽象或者接口 //選臺和播放 interface IVideoSource { string GetTvGuide(); string PlayVideo(); } //抽象或者接口實現 ---》不一樣的電臺 class LocalCabelTv : IVideoSource { const string SOURCE_NAME = "Local Cabel TV"; string IVideoSource.GetTvGuide() { return string.Format("Getting TV guide from - {0}", SOURCE_NAME); } string IVideoSource.PlayVideo() { return string.Format("Playing - {0}", SOURCE_NAME); } } //具體實現 電臺2 class LocalDishTv : IVideoSource { const string SOURCE_NAME = "Local DISH TV"; string IVideoSource.GetTvGuide() { return string.Format("Getting TV guide from - {0}", SOURCE_NAME); } string IVideoSource.PlayVideo() { return string.Format("Playing - {0}", SOURCE_NAME); } } //智能電視,橋接載體,這個載體很重要 class MySuperSmartTV { IVideoSource currentVideoSource = null; public IVideoSource VideoSource { get { return currentVideoSource; } set { currentVideoSource = value; } } public void ShowTvGuide() { if (currentVideoSource != null) { Console.WriteLine(currentVideoSource.GetTvGuide()); } else { Console.WriteLine("Please select a Video Source to get TV guide from"); } } public void PlayTV() { if (currentVideoSource != null) { Console.WriteLine(currentVideoSource.PlayVideo()); } else { Console.WriteLine("Please select a Video Source to play"); } } } //客戶端調用 class SuperSmartTvController { static void Main(string[] args) { MySuperSmartTV myTv = new MySuperSmartTV(); //載體 Console.WriteLine("請選擇電臺節目"); ConsoleKeyInfo input = Console.ReadKey(); // 用戶選擇不一樣的電臺後 將節目橋接給電視播放 switch (input.KeyChar) { case '1': myTv.VideoSource = new LocalCabelTv(); break; case '2': myTv.VideoSource = new LocalDishTv(); break; } Console.WriteLine(); //選臺顯示 myTv.ShowTvGuide(); //電視開始播放 myTv.PlayTV(); Console.WriteLine(); } }
3.組合模式(把多個對象組成樹狀結構來表示局部與總體,這樣用戶能夠同樣的方式來對待單個對象和對象的組合。)架構
組合模式爲了使用戶能夠用同樣的方式對待單個對象和組合對象的目的,那麼都必須實現同樣的基類或者接口來實現,這就是它的原理。ide
//繼承相同的基類或者接口。 組件 public abstract class Component { protected readonly string name; protected Component(string name) { this.name = name; } public abstract void Operation(); public abstract void Display(int depth); } //實現單個對象 子組件 public class Leaf : Component { public Leaf(string name) : base(name) { } public override void Operation() { Console.WriteLine("Leaf."); } public override void Display(int depth) { Console.WriteLine(new String('-', depth) + name); } } //組合組件對象 class Composite : Component { private readonly List<Component> _children = new List<Component>(); public Composite(string name) : base(name) { } //組合葉子組件 刪除或者增長 public void AddChild(Component component) { _children.Add(component); } public void RemoveChild(Component component) { _children.Remove(component); } public override void Display(int depth) { Console.WriteLine(new String('-', depth) + name); foreach (Component component in _children) { component.Display(depth + 2); } } public override void Operation() { string message = string.Format("Composite with {0} child(ren).", _children.Count); Console.WriteLine(message); } } //客戶端調用 static class Program { static void Main() { //根組合組件增長倆單個對象組件 var root = new Composite("root"); root.AddChild(new Leaf("Leaf 1")); root.AddChild(new Leaf("Leaf 2")); //第二個組合組件增長倆單個對象組件 var comp = new Composite("Composite C"); comp.AddChild(new Leaf("Leaf C.1")); comp.AddChild(new Leaf("Leaf C.2")); //將第二個組合組件計入根組合組件 root.AddChild(comp); root.AddChild(new Leaf("Leaf 3")); //實例化一個單個組件,並加入到根組合組件中 var leaf = new Leaf("Leaf 4"); root.AddChild(leaf); root.RemoveChild(leaf); //統一調用全部的 root.Display(1); } }
四、裝飾模式(有時也叫修飾模式,它是向某個對象動態地添加更多的功能。修飾模式是除類繼承外另外一種擴展功能的方法。)ui
//一個組件基類 public abstract class ComponentBase { public abstract void Operation(); } //實現基類的標準組件 class ConcreteComponent : ComponentBase { public override void Operation() { Console.WriteLine("ConcreteComponent.Operation()"); } } //爲了給Operation方法增長額外功能,集成自組件基類的基類,起到裝飾做用 public abstract class DecoratorBase : ComponentBase { private readonly ComponentBase _component; protected DecoratorBase(ComponentBase component) { _component = component; } public override void Operation() { _component.Operation(); } } //增長額外功能給Operation方法,這裏擴展類中調用的是擴展的基類 public class ConcreteDecorator : DecoratorBase { public ConcreteDecorator(ComponentBase component) : base(component) { } public override void Operation() { base.Operation(); Console.WriteLine("這裏能夠增長額外的功能或者在該類中實現其餘方法在此處調用"); } } //客戶端調用 static class Program { static void Main() { //我是一個標準組件 var component = new ConcreteComponent(); //擴展了功能的組件 var decorator = new ConcreteDecorator(component); decorator.Operation(); //該方法被加強了其餘功能 } }
五、外觀模式(爲子系統中的一組接口提供一個一致的界面, 外觀模式定義了一個高層接口,這個接口使得這一子系統更加容易使用。)this
這個模式現實中使用在外面常常在系統架構中的包裝層(Facade層),將不少子類都封裝在一塊兒,讓後共外部調用。spa
//A子系統 功能方法返回數字1 public class Class1A { public int Method1A() { Console.WriteLine("Class1A.Method1A return value: 1"); return 1; } } //B子系統 public class Class1B { public int Method1B(int param) { Console.WriteLine("Class1B.Method1B return value: {0}",param+1); return param+1; } } //2A子系統 public class Class2A { public int Method2A(int param) { Console.WriteLine("Class2A.Method2A return value: {0}",param+2); return param+2; } } //2B子系統 public class Class2B { public void Method2B(int param1, int param2) { Console.WriteLine("Class2B.Method2B return value: {0}", param1+param2 ); } } //外觀模式的包裝層 public class Facade { public void PerformAction() { var c1a = new Class1A(); var c1b = new Class1B(); var c2a = new Class2A(); var c2b = new Class2B(); var result1a = c1a.Method1A(); var result1b = c1b.Method1B(result1a); var result2a = c2a.Method2A(result1a); c2b.Method2B(result1b, result2a); } } //外部客戶端調用 static class Program { static void Main() { //供外部統一調用 Facade facade = new Facade(); facade.PerformAction(); } }
該模式有點相似原型模式(建造類型的),不一樣的是享元模式是結構類型的模式,原始對象(共享的對象,即不可變部分。俗稱不可變內部狀態)可能產生不一樣的小顆粒對象(可變部分,例如參數。俗稱可變外部狀態),封裝了原始對象進入一個工廠,使用中能夠沒必要重複建立對象。代理
//抽象層,提供共享使用要實現的內部方法 public abstract class FlyweightBase { public abstract void StatefulOperation(object o); } //共享的類 public class ConcreteFlyweight : FlyweightBase { public override void StatefulOperation(object o) { Console.WriteLine(o); } } //非共享類 public class UnsharedFlyweight : FlyweightBase { private object _state; public override void StatefulOperation(object o) { _state = o; Console.WriteLine(_state); } } //共享工廠類,將同對象細粒度的對象保存到hashtable public class FlyweightFactory { private readonly Hashtable _flyweights = new Hashtable(); public FlyweightBase GetFlyweight(string key) { if (_flyweights.Contains(key)) { return _flyweights[key] as FlyweightBase; } var newFlyweight = new ConcreteFlyweight(); _flyweights.Add(key, newFlyweight); return newFlyweight; } } //客戶端調用 static class Program { static void Main() { int extrinsicstate = 22; //一下三個是共享三個細粒度對象,其實他們只有一個原對象實例 var factory = new FlyweightFactory(); var flyweightA = factory.GetFlyweight("A"); flyweightA.StatefulOperation(--extrinsicstate); var flyweightB = factory.GetFlyweight("B"); flyweightB.StatefulOperation(--extrinsicstate); var flyweightC = factory.GetFlyweight("C"); flyweightC.StatefulOperation(--extrinsicstate); //非共享的對象 var unsharedFlyweight = new UnsharedFlyweight(); unsharedFlyweight.StatefulOperation(--extrinsicstate); } }
代理模式客戶端不能直接訪問原對象,只能經過代理中介訪問。某些狀況就是客戶端沒法訪問原對象或者更重要的是代理要作點手腳才讓你訪問呢!,就只能請代理來幫忙了。
//代理及實際對象的基類 public abstract class SubjectBase { public abstract void Operation(); } //實際原對象 public class RealSubject : SubjectBase { public override void Operation() { Console.WriteLine("RealSubject.Operation"); } } //代理 public class Proxy : SubjectBase { private RealSubject _realSubject; public override void Operation() { if (_realSubject == null) _realSubject = new RealSubject(); _realSubject.Operation(); } } //客戶端使用代理訪問原對象的方法 static class Program { static void Main() { var proxy = new Proxy(); proxy.Operation(); } }