前言:毫無疑問 ,學習一些設計模式,對咱們的編程水平的提升幫助很大。寫這個博客的時候本身剛開始學習設計模式,不免有錯,歡迎評論指正。程序員
我學設計模式的第一本書是「大話設計模式」。算法
1.爲何要學設計模式?編程
設計模式的存在就是爲了抵禦需求變動。學會了這些思想,開始一個項目的時候考慮的更多,當用戶提出變動的時候項目改動更少。設計模式
2.怎麼才能學會設計模式?安全
我不知道,不過輪子哥(vczh)文章中的一句話,我以爲對,就是:「設計模式就是由於狀況複雜了因此纔會出現的,因此咱們只能經過複雜的程序來學習設計模式。你無論看別人的程序也好,本身寫程序練習也好,那必需要複雜,複雜到你不用設計模式就作不下去,這才能起到學習設計模式的做用」。因此,我準備選擇一些本身用到的設計模式,經過寫代碼的方式去熟悉它們。ide
一.簡單工廠模式(Simple Factory Pattern)函數
場景描述:製做一個計算器。學習
1.實現加減乘除。優化
2.之後有其它算法的時候,容易維護。ui
工廠類
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Threading.Tasks; 6 //Author:cuishiyu 7 //2016.08.13 8 namespace OperationByFactory.Class 9 { 10 //運算工廠類 11 class OperationFactory 12 { 13 public static Operation createOperation(string operate) 14 { 15 Operation oper = null; 16 switch (operate) 17 { 18 case "+": 19 oper = new OperationAdd(); 20 break; 21 case "-": 22 oper = new OperationSub(); 23 break; 24 case "*": 25 oper = new OperationMul(); 26 break; 27 case "/": 28 oper = new OperationDiv(); 29 break; 30 } 31 return oper; 32 } 33 } 34 }
運算類
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Threading.Tasks; 6 //Author:cuishiyu 7 //2016.08.13 8 namespace OperationByFactory.Class 9 { 10 //運算類 11 class Operation 12 { 13 private double _numberA = 0; 14 private double _numberB = 0; 15 16 public double NumberA 17 { 18 get 19 { 20 return _numberA; 21 } 22 23 set 24 { 25 _numberA = value; 26 } 27 } 28 29 public double NumberB 30 { 31 get 32 { 33 return _numberB; 34 } 35 36 set 37 { 38 _numberB = value; 39 } 40 } 41 42 public virtual double GetResult() 43 { 44 double result = 0; 45 return result; 46 } 47 } 48 }
加減乘除類
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Threading.Tasks; 6 //Author:cuishiyu 7 //2016.08.13 8 namespace OperationByFactory.Class 9 { 10 //加法類 11 class OperationAdd:Operation 12 { 13 public override double GetResult() 14 { 15 return NumberA + NumberB; 16 } 17 } 18 }
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Threading.Tasks; 6 //Author:cuishiyu 7 //2016.08.13 8 namespace OperationByFactory.Class 9 { 10 //減法類 11 class OperationSub:Operation 12 { 13 public override double GetResult() 14 { 15 return NumberA - NumberB; 16 } 17 } 18 }
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Threading.Tasks; 6 //Author:cuishiyu 7 //2016.08.13 8 namespace OperationByFactory.Class 9 { 10 //乘法類 11 class OperationMul:Operation 12 { 13 public override double GetResult() 14 { 15 return NumberA * NumberB; 16 } 17 } 18 }
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Threading.Tasks; 6 //Author:cuishiyu 7 //2016.08.13 8 namespace OperationByFactory.Class 9 { 10 //除法類 11 class OperationDiv:Operation 12 { 13 public override double GetResult() 14 { 15 if(NumberB== 0) 16 throw new Exception("除數不能爲0"); 17 return NumberA / NumberB; 18 } 19 } 20 }
總結:簡單工廠模式很簡單,重要的是。這個設計模式是怎麼一步步造成的、和這樣作的好處有哪些。
1.可移植性號,不管是控制檯程序,Windows程序,Web程序,均可以用這段代碼。
2.擴展性好,更安全,之後增長平方,立方,開根號等運算的時候,增長一個相應的類,而後再Switch裏增長分支就行了。同時也不用擔憂程序員修改原先寫好的加減乘除類,使得原先的代碼不會被有意或者無心的修改,因此更安全。
3.(1)編程儘量避免重複的代碼。(2)對業務進行封裝,儘量的讓業務邏輯和頁面邏輯分開,讓它們的耦合度降低,這樣更容易維護和擴展。
4.你們能夠熟悉一下UML類圖,畫出來以後理解更直觀。
二.策略模式(strategy Pattern)
場景描述:商場的收銀軟件,收銀員根據客戶所購買的商品單價和數量進行收費。
1.要考慮到打折的狀況(好比過節打8折)。
2.要考慮滿A返B的狀況(好比滿300返100)。
3.考慮之後發生其它狀況是,儘可能作到代碼容易更改,安全的更改。
注:部分代碼是僞代碼
抽象策略類
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Threading.Tasks; 6 7 namespace PromotionByStrategy 8 { 9 //抽象策略類 10 abstract class CashSuper 11 { 12 public abstract double acceptCatch(double money); 13 } 14 }
返利收費子類
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Threading.Tasks; 6 7 namespace PromotionByStrategy 8 { 9 //返利收費子類 10 class CashReturn : CashSuper 11 { 12 private double moneyCondition = 0.0d; 13 private double moneyReturn = 0.0d; 14 public CashReturn(string moneyCondition, string moneyReturn) 15 { 16 this.moneyCondition = double.Parse(moneyCondition); 17 this.moneyReturn = double.Parse(moneyReturn); 18 } 19 public override double acceptCatch(double money) 20 { 21 double result = money; 22 if (money >= moneyCondition) 23 { 24 result = money - Math.Floor(money / moneyCondition) * moneyReturn; 25 } 26 return result; 27 } 28 } 29 }
打折收費子類
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Threading.Tasks; 6 7 namespace PromotionByStrategy 8 { 9 //打折收費子類 10 class CashRebate : CashSuper 11 { 12 private double moneyRebate = 1d; 13 14 //構造函數傳入打折信息 15 public CashRebate(string moneyRebate) 16 { 17 this.moneyRebate = double.Parse(moneyRebate); 18 } 19 20 public override double acceptCatch(double money) 21 { 22 return money * moneyRebate; 23 } 24 } 25 }
正常收費子類
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Threading.Tasks; 6 7 namespace PromotionByStrategy 8 { 9 //正常收費子類 10 class CashNormal : CashSuper 11 { 12 public override double acceptCatch(double money) 13 { 14 return money; 15 } 16 } 17 }
策略和簡單工廠的結合
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Threading.Tasks; 6 7 namespace PromotionByStrategy 8 { 9 //策略和簡單工廠的結合 10 class CashContext 11 { 12 //收錢的父類 13 CashSuper cs = null; 14 15 /// <summary> 16 /// 構造函數初始化收費類型對象 17 /// </summary> 18 /// <param name="type"></param> 19 public CashContext(string type)//傳入一個收費的類型 20 { 21 switch (type)//根據不一樣的類型實例化不一樣的收款算法對象 22 { 23 case"正常收費": 24 cs = new CashNormal(); 25 break; 26 case "滿A減B": 27 cs = new CashReturn("A", "B"); 28 break; 29 case "打X折": 30 cs = new CashRebate("0.X"); 31 break; 32 } 33 } 34 35 public double GetResult(double money) 36 { 37 return cs.acceptCatch(money); 38 } 39 } 40 }
客戶端的主要程序
1 double tatal = 0.0d; 2 //客戶端的主要程序 3 //傳入算法,和價格*數量,獲得應收的錢 4 public void btnOK_Click() 5 { 6 CashContext csuper = new CashContext("傳入收款的算法"); 7 double totalPrices = 0.0d; 8 totalPrices = csuper.GetResult(Convert.ToDouble("價格*數量")); 9 }
總結:在分析一個項目中,遇到不一樣的時間應用不一樣的業務規則,就能夠考慮使用策略模式處理這種變化的可能性。這個代碼還能夠優化,後面會用反射進行優化
三.單一職責原則(SRP)
注:3、4、五主要分享設計模式中用到的一些原則
就一個類而言,因該僅有一個引發它變化的緣由。一個類只行使一個功能,後面維護的時候會方便許多。
四.開放-封閉原則(The Open-Closeed Principle)
對軟件實體來講(類、模塊。函數)都要求知足:
兩大特徵:對擴張是開放的(Open for extension),對更改是封閉的(Closed for modification)。
在具體的實現過程當中,可按照下面作:
1.咱們在最初編碼的時候,假設變化不會發生。當發生變化的時候,咱們就建立抽象來隔離之後發生的同類變化。
2.當面對需求的時候,對程序的改動,是經過增長代碼而不是修改現有的代碼實現。
3.拒毫不成熟的抽象,和抽象自己一樣重要。
五.依賴倒轉原則
1.依賴倒轉原則:抽象不該該依賴細節,細節應該依賴抽象。
簡單解釋就是,針對接口編程而不是針對實現編程。
A.高模塊不該該依賴低層模塊。兩個都應該依賴抽象。
B.抽象不該該依賴細節,細節應該依賴抽象。
2.里氏代換原則:子類型必須可以替換掉他們的父類型。
簡單解釋就是,一個軟件實體若是使用的是一個父類的話,那麼必定使用於其子類,並且它察覺不出父類對象和子類對象的區別。
也就是說,在軟件裏面,把父類都替換成它的子類,程序行爲沒有變化。
六.裝飾模式
場景描述:寫一個給人搭配不一樣服飾的系統,相似QQ秀,或者遊戲皮膚之類的。
Person類
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Threading.Tasks; 6 7 namespace DressByDecorator 8 { 9 //Person類 10 class Person 11 { 12 public Person() 13 { } 14 15 private string name; 16 17 public Person(string name) 18 { 19 this.name = name; 20 } 21 22 public virtual void Show() 23 { 24 Console.WriteLine("裝扮的{0}",name); 25 } 26 } 27 }
服飾類,繼承Person類
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Threading.Tasks; 6 7 namespace DressByDecorator 8 { 9 //服飾類 10 class Finery : Person 11 { 12 protected Person componnet; 13 14 //打扮 15 public void Decorate(Person component) 16 { 17 this.componnet = component; 18 } 19 20 public override void Show() 21 { 22 if (componnet != null) 23 { 24 componnet.Show(); 25 } 26 } 27 } 28 }
具體的服飾類,下面舉兩個例子。
鞋子類,繼承服飾類。
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Threading.Tasks; 6 7 namespace DressByDecorator 8 { 9 //鞋子類 10 class Shose:Finery 11 { 12 public override void Show() 13 { 14 Console.WriteLine("鞋子"); 15 base.Show(); 16 } 17 } 18 }
T恤類,繼承服飾類。
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Threading.Tasks; 6 7 namespace DressByDecorator 8 { 9 //T恤類 10 class TShirts:Finery 11 { 12 public override void Show() 13 { 14 Console.WriteLine("T恤"); 15 base.Show(); 16 } 17 } 18 }
下面是main函數裏的實現
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Threading.Tasks; 6 7 namespace DressByDecorator 8 { 9 //Person類 10 class Person 11 { 12 public Person() 13 { } 14 15 private string name; 16 17 public Person(string name) 18 { 19 this.name = name; 20 } 21 22 public virtual void Show() 23 { 24 Console.WriteLine("裝扮的{0}",name); 25 } 26 } 27 }
裝飾模式(Decorator),動態地給一個對象添加一些額外的職責,就增長功能來講,裝飾模式比生成子類更加靈活。
總結:這個例子中,每個類都形式本身的功能。他們公有的功能都寫在了父類。能夠實現動態的添加更多的衣服。