設計模式?到底什麼是設計模式?仍是直接去抄一下定義吧。設計模式是針對上下文的特定問題的解決方案。也就是一種解決問題的思路。編程
在說設計模式以前,咱們仍是要提一下七大原則:開閉原則、依賴倒轉原則、單一職責原則、里氏替換原則、複合複用原則、迪米特原則、接口隔離原則。這幾個原則就是簡單的說一下,並非須要花太多的時間去說,由於說多了也記不出。設計模式
1、狀態模式mvc
當一個對象的內在狀態改變時容許改變其行爲,這個對象看起來像是改變了其類。其實吧,當我使用這個狀態模式的時候,感受這個狀態模式能夠理解成爲具體對象抽象化,就是咱們所說的子類父類的關係,父類中的方法都是通常化,子類具體實現就好了。使用這個模式的時候咱們須要定義一個入口對象(上下文環境)Context ,在這個對象中具體去實現你要實現的對象就好了。其實這樣作的好處就是咱們不用大量的去對相同結構的對象去寫一些相同的字段或者方法了,下面是網上的圖片:學習
這個state抽象類你能夠不用寫成抽象,也能夠寫成通常類或者接口,由於狀態模式的本質就是子類通常化。在這中模式中咱們通常會使用一個controller來管理狀態,不一樣的state在這個controller中進行切換。this
2、外觀模式spa
外觀模式是一種使用頻率很是好的結構型設計模式,它經過引入一個外觀角色來簡化客戶端與子系統之間的交互,爲複雜的子系統調用提供了一個統一的入口,下降子系統與客戶端之間的耦合度,且客戶端調用很是方便。設計
說到這裏,其實咱們並不難的理解外觀模式是用來減小耦合度的。咱們也能夠這樣去理解,在軟考中的1:m,這樣就能夠很容易去知道了1是指的客戶端,也就是外界訪問,那就是多個子系統。這裏要特別說明的一下的是,子系統之間是不能夠相互調用,若是調用的話就變成了中介者模式了。外界與內部調用是經過一箇中間變量來執行的。下面是圖:日誌
3、單例模式(跳過)code
4、中介者模式對象
首先第一句中介者模式的關係是m:n。爲了是思路更加明白,中介者模式只是對子系統之間而言的,並不對外界有影響。每一個子系統若是想要去調用別的子系統的話,咱們通常的作法不會讓他們直接去調用的,而是去找個中間變量去來管理他們,這個中間變量就是中介者。說到這裏咱們其實已經很明白外觀模式與中介者的區別了,可是咱們在實際開發中,咱們仍是會把他們放在一塊兒使用的,由於分外寫沒有必要。他們本質就是管理,使代碼之間的耦合下降,功能單一。這個是很是符合軟件開發的單一指責原則的。圖:
5、橋接模式
關於這個模式,咱們仍是先來看看這個模式的意圖吧。將抽象部分與它的實現部分分離,使他們能夠獨立的變化。在學習這個部分的時候,咱們不能把它單獨的來講,必定要與前面進行比較來學。狀態模式是將具體類抽象成一個類,客戶端與這個抽象類進行打交道,這個特色是一個實體,一個是抽象。咱們如今作的一件事情就是,當咱們的客戶變成多個具備相同特色,又有一些不一樣的時候的,那咱們有應該這麼去作呢?最好的辦法就是將客戶端也進行抽象,那麼就變成了兩個抽象類進行交互了,這樣的鏈接模式就是橋接模式。在這裏的時候咱們發現,就是在這前面的模式,他們都是爲了減小耦合的,爲了這個,就須要提取公共的特色,這個提取的過程就是抽象類。或者能夠這樣的去認爲,橋接模式就是兩個狀態模式。圖:
6、工廠模式
在面向對象編程中,最一般的方法是一個new操做符產生一個對象實例,new操做符就是用來構造對象實例的。可是在一些狀況下,new操做符直接生成對象會帶來一些問題。舉個例子說,許多類型對象的建立須要一系列的步驟:你可能須要計算或取得對象的初始設置;選擇生成哪一個子對象實例;或在生成你須要的對象以前必須先生成一個輔助功能的對象。在這些狀況新對象的創建就是一個「過程」。不只是一個操做,像一個大機器中的一個齒輪傳動。
工廠模式分爲簡單工廠模式、工廠方法模式、抽象工廠模式。咱們一個一個說明。
簡單工廠模式
代碼以下:
#region 產品類 //基類 通常的做用就是將子類的共有的方法聚集過來 //避免重複寫 public abstract class BWM { public BWM() { } } public class BWM320 : BWM { public BWM320() { Console.WriteLine("製造-->BWM320"); } } public class BWM523 : BWM { public BWM523() { Console.WriteLine("製造-->BWM523"); } } #endregion #region 工廠類 public class Factory { public BWM CreateBWM(int type) { switch (type) { case 320: return new BWM320(); case 523: return new BWM523(); default: break; } return null; } } #endregion #region 客戶類 class Program { static void Main(string[] args) { Factory factory = new Factory();//實例化簡單工廠 BWM bWM320 = factory.CreateBWM(320); BWM bwm523 = factory.CreateBWM(523); Console.ReadKey(); } } #endregion
咱們從上面的代碼上能夠看出,先將產品的基類寫出來,而後再生成子類,這個部分就是產品類;接着咱們的作法就是直接建立一個工廠類,這個工廠類是一個普通的類,在這個裏面咱們寫一個方法,在外面能夠經過這個方法傳參,就能夠在factory類中建立你須要指定的產品類了,可是這個方法有一個缺點,若是咱們這個時候再來一個產品類的話,咱們就是在factory再進行修改。這樣作的方式是很差的,由於咱們在設計軟件軟件中有一個原則 就是對拓展開放,對修改封閉。就是咱們在進行建立的時候,咱們應該知道若是多個類他們的方法是同樣的,可是須要不一樣的數據的話,咱們就應該爲他們建立一個基類,因此這個factory也是應該建立一個基類的,全部下面就是第二個了。
工廠方法模式
#region 產品類 public abstract class BMW { public BMW() { } } public class BMW320 : BMW { public BMW320() { Console.WriteLine("製造-->BMW320"); } } public class BMW523 : BMW { public BMW523() { Console.WriteLine("製造-->BMW523"); } } #endregion #region 建立工廠類 interface FactoryBMW { BMW CreateBMW(); } public class FactoryBMW320 : FactoryBMW { public BMW CreateBMW() { return new BMW320(); } } public class FactoryBMW523 : FactoryBMW { public BMW CreateBMW() { return new BMW523(); } } #endregion class Program { static void Main(string[] args) { FactoryBMW320 factoryBMW320 = new FactoryBMW320(); BMW320 bMW320 = (BMW320)factoryBMW320.CreateBMW(); FactoryBMW523 factoryBMW523 = new FactoryBMW523(); BMW523 bMW523 = (BMW523)factoryBMW523.CreateBMW(); Console.ReadKey(); } }
其實咱們不難發現就是將工廠進行抽象化,就是所說的那個提取基類,咱們在使用的時候只須要用指定的基類。若是你是須要使用BMW320的話,你只要去實例化BMW320的工廠類就好了,可是這樣的話仍是出現一個問題,若是咱們又有新的功能的話,又怎麼辦了?其實在這種功能常常進行變動的地方,咱們必定要注意抽象方法提取基類的思想。
下面就是抽象工廠方法
#region 產品類 //發動機以及型號 public interface Engine { } public class EngineA : Engine { public EngineA() { Console.WriteLine("製造-->EngineA"); } } public class EngineB : Engine { public EngineB() { Console.WriteLine("製造-->EngineB"); } } //空調以及型號 public interface Aircondition { } public class AirconditionA : Aircondition { public AirconditionA() { Console.WriteLine("製造-->AirconditionA"); } } public class AirconditionB : Aircondition { public AirconditionB() { Console.WriteLine("製造-->AirconditionB"); } } #endregion #region 建立工廠類 //建立工廠的接口 public interface AbstractFactory { //製造發動機 Engine CreateEngine(); //製造空調 Aircondition CreteAirconition(); } //爲寶馬320系列生產配件 public class FactoryBMW320 : AbstractFactory { public Engine CreateEngine() { return new EngineA(); } public Aircondition CreteAirconition() { return new AirconditionA(); } } //爲寶馬523系列生產配件 public class FactoryBMW523 : AbstractFactory { public Engine CreateEngine() { return new EngineB(); } public Aircondition CreteAirconition() { return new AirconditionB(); } } #endregion class Program { static void Main(string[] args) { //生產寶馬320系列配件 FactoryBMW320 factoryBMW320 = new FactoryBMW320(); factoryBMW320.CreateEngine(); factoryBMW320.CreteAirconition(); //生產寶馬523系列配件你 FactoryBMW523 factoryBMW523 = new FactoryBMW523(); factoryBMW523.CreateEngine(); factoryBMW523.CreteAirconition(); Console.ReadKey(); } }
其實這樣的作法就是咱們給工廠的子類提供一個接口,若是咱們添加需求的時候,咱們就能夠在工廠子類裏進行顯示。仍是那句話,提取基類。
不管是簡單工廠模式,工廠方法模式,仍是抽象工廠模式,他們都屬於工廠模式,在形式和特色上也是極爲類似的,他們的最終目的都是解耦。在使用時,咱們沒必要去在乎這個模式究竟是工廠模式仍是抽象工廠模式,由於他們之間的演變經常是使人捉摸不透的。常常你會發現,明明使用的工廠模式,當新需求來臨時,稍加修改,加入了一個新的方法後,因爲類中的產品構成了不一樣等級結構中的產品族,它就變成抽象工廠模式,當減小一個方法時的提供的產品再也不構成產品族以後,它就演變了工廠方法模式。
七建造者模式
建造者模式使用多個簡單的對象一步一步構造一個複雜的對象。這種類型的設計模式屬於建立者模式,它提供了一種建立對象的對象方式。在編程中,咱們仍是要知道一點的,就是當你去建立一個對象的時候,若是這個對象的功能實在是太多了。好比說,這個對象須要建立身體,須要建立武器,須要建立特效等等,當咱們把它的具體實現類所有放在一個類中去完成,這顯然是很差的,由於這個違背了對修改關閉,對拓展開放的原則。管理者其實要作的就是咱們只要知道流程就好了,具體的可讓各個部分去作,其實建造者模式就是這個原理。建造者會把一個功能龐大的對象進行分解,每個部分只須要去完成一個小的部分,而後管理者再進行組裝,若是有的地方要使用對象的話,就直接向這個管理者提要求,讓管理者去作就好了。
十一命令模式
將一個請求封裝成一個對象(即咱們建立的command對象)從而使你可用不一樣的請求對客戶進行參數化;對請求排隊或記錄請求日誌,以及支持可撤銷的操做。子軟件系統中,行爲請求者與行爲實現者一般是一種緊耦合的關係,但在某些場合,好比須要對行爲進行記錄、撤銷或者重作、事務等處理時,這種沒法抵禦變化的緊耦合的設計模式就不太合適了。咱們在設計軟件的時候,若是讓接受與發送者兩個職能放在一塊兒的話,就會出現耦合性比較高的狀況,咱們要作的就是將職能進行分開,讓發送與接受分紅單獨的類
/// <summary> /// 接收者類,知道如何實施與執行一個請求相關的操做,任何類均可能做爲一個接收者 /// </summary> public class Receiver { /// <summary> /// 真正的命令實現 /// </summary> public void Action() { Console.WriteLine("Excete request"); } } /// <summary> /// 抽象命令類,用來聲明執行操做的接口 /// </summary> public interface ICommand { void Excete(); } /// <summary> /// 具體命令類,實現具體命令 /// </summary> public class ConcerteCommand : ICommand { private Receiver receiver; //具體命令類包含有一個接收者,將這個接收者對象綁定與一個動做 public ConcerteCommand(Receiver receiver) { this.receiver = receiver; } /// <summary> /// 說這個實現是虛的,由於他是經過調用接收者相對應的操做來實現Excete的 /// </summary> public void Excete() { receiver.Action(); } } /// <summary> /// 調度類,要求該命令執行這個請求 /// </summary> public class Invoker { private ICommand command; /// <summary> /// 設置命令 /// </summary> /// <param name="command"></param> public void SetCommand(ICommand command) { this.command = command; } /// <summary> /// 執行命令 /// </summary> public void ExceteCommand() { command.Excete(); } } class Program { static void Main(string[] args) { Receiver receiver = new Receiver(); ICommand command = new ConcerteCommand(receiver); Invoker invoker = new Invoker(); invoker.SetCommand(command); invoker.ExceteCommand(); Console.ReadKey(); } }
咱們從代碼中能夠看出,咱們先要初始化一個receiver(接收者類),這個類是你不須要知道你去讓外界去工做,只須要外界發出命令請求的時候,這個類只須要去作就好了,這個是一個單向的,就比較像mvc模式中的view類同樣,只須要去作就好了。另外再說一句就是這個receiver類是一個具體執行的類。