設計模式是軟體開發討論中,亙古不變的話題,今天又拿出來說道兩句,也是對設計模式的一個複習吧。
Factory 方法模式
Factory 方法模型定義了一個用於建立對象的介面,讓子類決定執行個體化哪一個類,原廠模式使一個類的執行個體化延遲到了其子類中。Factory 方法模式是最佳化的簡單原廠模式,它很好的支援了“開閉原則”。每一個具體的工廠只能構建一個類的對象。具體工廠類與產品類是一對一的關係。
/// <summary> /// 抽象產品類/// </summary> public class Product{public Product(){Console.Write("new Product");} }/// <summary> /// 具體產品類A/// </summary>public class ConcreteProductA:Product {public ConcreteProduct(){Console.Write("建立了一個 ConcreteProductA");}}/// <summary> /// 具體產品類B/// </summary>public class ConcreteProductB:Product {public ConcreteProduct(){Console.Write("建立了一個 ConcreteProductB");}}/// <summary> /// 抽象的建立者/// </summary>abstract public class Creator{//抽象的Factory 方法public abstract Product FactoryMethod();}/// <summary> /// 具體方法工廠A/// </summary>public class ConcreteCreatorA:Creator{//返回一個產品A的對象public override Product FactoryMethod(){return new ConcreteProductA();}}/// <summary> /// 具體方法工廠B/// </summary>public class ConcreteCreatorB:Creator{//返回一個產品B的對象public override Product FactoryMethod(){return new ConcreteProductB();}}//client端static void Main(string[] args) { Creator c = new ConcreteCreatorA(); Product p = c.FcatoryMethod(); c = new ConcreteCreatorB(); p = c.FcatoryMethod(); Console.ReadLine();}
適配器模式Adapter
適配器模式是將一個類的介面轉換成客戶希望的另外一個介面。適配器模式使得原本由於介面不相容而不能一起工作的那些類可以一起工作。
兩個成熟的類需要通訊,但是介面不同,由於開閉原則,我們不能去修改這兩個類的介面,所以就需要一個適配器來完成銜接過程。
變壓器就是很好的適配器模式的例子。用電裝置所需要的電壓是9V,但是電線上的電壓卻是220V的,我們不能去更改它們的電壓輸入或輸出,所以我們用到了變壓器。變壓器是220V的輸入,9V的輸出。這樣就可以將200V的電壓變為9V的電壓,用變壓器將用電裝置串連到了電線上工作了。
上面兩幅圖中,都是Client端需要Request這個方法,但是Adaptee沒有這個方法,所以就需要提供一個中介軟體/封裝類(Wrapper)Adapter類來銜接。不同的是第一幅圖Adapter繼承自Adaptee,而第二幅圖是在Adapter類中封裝了一個Adaptee的執行個體。這就決定了第一幅圖講的是“類的結構模式”,而第二幅圖則是“對象的結構模式”。
/// <summary> /// 目標介面,客戶所期待的介面。/// </summary> public class Target{public virtual void Request(){Console.Write("我是本系統中的普通請求.");}}/// <summary> /// 適配器,匹配2個介面不一致的類/// </summary> public class Adapter:Target{private Adaptee adaptee = new Adaptee();public void Request(){adaptee.SpecificRequest();}}/// <summary> /// 源介面,與客戶期待的介面不一致/// </summary> public class Adaptee(){public void SpecificRequest(){Console.Write("我是原有的真實調用的系統");}}//client端static void Main(string[] args) { Target t = new Adapter();t.Request();Console.ReadLine();}
橋接模式 Bridge
橋接模式將抽象部分與它的實現部分分離,使它們都可以獨立地變化。它很好的支援了開閉原則和組合及複用原則。實現系統可能有多角度分類,每一種分類都有可能變化,那麼就把這些多角度分離出來讓他們獨立變化,減少他們之間的耦合。
2個相互耦合的系列,每個系列都有各自的產品變動。將這2個系列抽象成2個角色類,將各自的變化封裝到對象的角色類中,然後再將2個角色類之間用組合的關係表示,這樣就大大簡化了使用類繼承的複雜性,邏輯變得清晰了,易於擴充和維護。
橋接模式封裝了變化,完成瞭解耦,實現了弱耦合。
/// <summary> /// 抽象部分/// </summary> public class Abstraction{protected Implementor implementor;public void SetImplementor(Implementor implementor){this.implementor = implementor;}public virtual void Operation(){implementor.OperationImp();}}/// <summary> /// 被提煉的抽象部分/// </summary> public class RefinedAbstraction:Abstraction{public override void Operation(){implementor.OperationImp();}}/// <summary> /// 實現部分/// </summary> abstract public class Implementor{public abstract void OperationImp();}/// <summary> /// 具體實現A/// </summary> public class conscreteImplementorA:Implementor{pulic override void OperationImp(){Console.Write("我是具體的A");}}/// <summary> /// 具體實現B/// </summary> public class conscreteImplementorB:Implementor{pulic override void OperationImp(){Console.Write("我是具體的B");}}//client端static void Main(string[] args) { Abstraction ab = new RefinedAbstraction();ab.SetImplementor(new conscreteImplementorA());ab.Operaton();ab.SetImplementor(new conscreteImplementorB());ab.Operaton();Console.ReadLine();}
具體的執行個體可以看我的另一篇博文《面與鹵的Queqiao相會——橋接模式》
裝飾模式 Decorator
裝飾模式動態地給一個對象添加一些額外的職責,就增加功能來說,它比產生子類更靈活。也可以這樣說,裝飾模式把複雜類中的核心職責和裝飾功能區分開了,這樣既簡化了複雜類,有去除了相關類中重複的裝飾邏輯。裝飾模式沒有通過繼承原有類來擴充功能,但卻達到了一樣的目的,而且比繼承更加靈活,所以可以說裝飾模式是繼承關係的一種替代方案。裝飾模式解耦了核心和裝飾功能,所以也是強調了松耦合。
/// <summary> /// 最高介面,被裝飾者和“裝飾品”都繼承於此/// </summary> abstract public class Component{public abstract void Operation();}/// <summary> /// 具體的被裝飾者/// </summary> public class Concretecomponent:Component{public override void Operation(){Console.Write("具體對象的裝飾操作");}}/// <summary> /// 裝飾類/// </summary> abstract public class Decorator:Component(){protected Component component;public void SetComponent(Component component){this.component = component;}public override void Operation(){if(component!=null) component.Operation();}}/// <summary> /// 具體的裝飾類A/// </summary> public class ConcreteDecoratorA:Decorator{private string addedState;public override void Operation(){base.Operation();addedState="New State";Console.Write("具體裝飾A的操作(添加了新的狀態)");}}/// <summary> /// 具體的裝飾類B/// </summary> public class ConcreteDecoratorB:Decorator{public override void Operartion(){base.Operation();AddedBehavior();Console.WriteLine("具體裝飾B的操作(添加了新的方法)");}private void AddedBehavior(){//添加新的行為}}//client端static void Main(string[] args) { Concretecomponent c = new Concretecomponent();Decorator d1 = new ConcreteDecoratorA();Decorator d2 = new ConcreteDecoratorB();d1.SetComponent(c);d2.SetComponent(d1);//注意這裡裝飾的是d1,因為這裡的d1是裝飾了d1的c。d2.Operation();Console.ReadLine();}
面板模式 Facade
面板模式為子系統中的一組介面提供了一個一致的介面,此模式定義了一個高層介面,這個介面使得這些子系統更加容易使用。
面板模式中,客戶對各個具體的子系統是不瞭解的,所以對這些子系統進行了封裝,對外只提供了使用者所明白的單一而簡單的介面,使用者直接使用這個介面就可以完成操作,而不用去理睬具體的過程,而且子系統的變化不會影響到使用者,這樣就做到了資訊隱蔽。
這就相當於新生接待員。新生對入學流程不清楚,但是接待員學長可是明白的。學生跟著接待員就可以把各個手續辦理完畢了。可以說面板模式封裝了細節。
/// <summary> /// 高層的統一介面,封裝了子系統繁雜的介面。/// </summary> public class Facade{private SubSystemOne one;private SubSystemTwo two;private SubSystemThree three;public Facade(){one = new SubSystemOne();two = new SubSystemTwo();three = new SubSystemThree();}public void MethodA(){one.MethodOne();two.MethodTwo();}public void MethodB(){one.MethodOne();three.MethodThree();}}/// <summary> /// 子系統One。/// </summary> public class SubSystemOne{public void MethodOne(){Console.Write("我是One");}}/// <summary> /// 子系統Two/// </summary> public class SubSystemTwo{public void MethodTwo(){Console.Write("我是Two");}}/// <summary> /// 子系統Three/// </summary> public class SubSystemThree{public void MethodThree(){Console.Write("我是Three");}}//client端static void Main(string[] args) {Facade f1 = new Facade();f1.MethodA();Facade f2 = new Facade();f2.MethodB();Console.ReadLine();}
策略模式 Strategy
策略模式定義一系列的演算法,把它們一個個封裝起來,並且使它們可以相互替換。本模式使得演算法的變化不會影響到使用演算法的客戶。
策略模式將每一個演算法封裝到一個具有公用介面的獨立類中,解除了客戶與具體演算法的直接耦合,是客戶改變演算法更為容易。
策略模式+簡單工廠+反射+設定檔可以組成更為靈活的方式。
/// <summary> /// 演算法的公用介面/// </summary> abstract public class Strategy{public abstract void AlgorithmInterface();}/// <summary> /// 具體演算法A/// </summary> public class ConcreteStrategyA:Strategy{public override void AlgorithmInterface(){Console.Write("具體演算法A");}}/// <summary> /// 具體演算法B/// </summary> public class ConcreteStrategyB:Strategy{public override void AlgorithmInterface(){Console.Write("具體演算法B");}}/// <summary> /// 具體演算法C/// </summary> public class ConcreteStrategyC:Strategy{public override void AlgorithmInterface(){Console.Write("具體演算法C");}}/// <summary> /// 上下文,用來維護一個對Strategy對象的引用。/// </summary> public class Context{private Strategy strategy;public Context(Strategy strategy){this.strategy=strategy;}//上下文介面public void ContextInterface(){strategy.AlgorithmInterface();}}//client端static void Main(string[] args){Context context = new Context(new ConcreteStrategyA());context.ContextInterface();context = new Context(new ConcreteStrategyB());context.ContextInterface();context = new Context(new ConcreteStrategyC());context.ContextInterface();Console.ReadLine();}
觀察者模式 Observer
觀察者模式定義了對象間的一種一對多的依賴關係,當一個對象的狀態發生變化時,所有依賴它的對象都會得到通知,並被自動更新,
系統中有兩個方面,其中一個方面依賴與另一個方面,我們把這兩個方面抽象,是各自可以獨立的變化和複用。
就像我們現在所用到的分層,不就是一層層的依賴嗎?還有系統組件升級,系統功能也跟著變化,這也屬於觀察者模式。
/// <summary> /// 抽象觀察類/// </summary> abstract public class Observer{public abstract void Update();}/// <summary> /// 具體觀察類/// </summary> public class Concreteobserver:Observer{private string name;private string observerState;private ConcreteSubject subject;public Concreteobserver(ConcreteSubject subject,string name){this.subject=subject;this.name= name;}public override void Update(){observerState=subject.GetState();Console.write("觀察者{0}的新狀態是{1}",name,observerState);}}/// <summary> /// 抽象主題類/// </summary> abstract public class Subject(){private List<observer> observers = new List<observer>() ;public void Attach(Observer observer){observers.Add(Observer);}public void Detach(Observer Observer){observers.Remove(Observer);}public void NotifyObservers(){foreach(Observer o in observers){o.Update();}}}/// <summary> /// 具體主題類/// </summary> public class ConcreteSubject:Subject{private string subjectState;public string SubjectState{get{return subjectstate;}set{subjectstrate=value;}}public void GetState(){return subjectstate;}}//client端static void Main(string[] args) { ConcreteSubject c = new ConcreteSubject();Concreteobserver o1 = new Concreteobserver(c,"X");Concreteobserver o2 = new Concreteobserver(c,"Y");Concreteobserver o3 = new Concreteobserver((c,"Z");c.Attach(o1);c.Attach(o2);c.Attach(o3);c.subjectstate="abc";c.Nofify();Console.ReadLine();}
欲瞭解其他模式,請查看我的這3篇博文:
《設計模式之建立型模式》
《設計模式之結構型模式》
《設計模式之行為型模式》