設計模式("大話設計模式"讀書筆記 C#實現)

前言:毫無疑問 ,學習一些設計模式,對咱們的編程水平的提升幫助很大。寫這個博客的時候本身剛開始學習設計模式,不免有錯,歡迎評論指正。程序員

        我學設計模式的第一本書是「大話設計模式」。算法

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 }
View Code

運算類

 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 }
View Code

加減乘除類

 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 }
View Code
 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 }
View Code
 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 }
View Code
 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 }
View Code

 總結:簡單工廠模式很簡單,重要的是。這個設計模式是怎麼一步步造成的、和這樣作的好處有哪些。

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 }
View Code

返利收費子類

 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 }
View Code

打折收費子類

 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 }
View Code

正常收費子類

 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 }
View Code

策略和簡單工廠的結合

 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 }
View Code

客戶端的主要程序

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         }
View Code

總結:在分析一個項目中,遇到不一樣的時間應用不一樣的業務規則,就能夠考慮使用策略模式處理這種變化的可能性。這個代碼還能夠優化,後面會用反射進行優化

三.單一職責原則(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 }
View Code

服飾類,繼承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 }
View Code

具體的服飾類,下面舉兩個例子。

鞋子類,繼承服飾類。

 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 }
View Code

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 }
View Code

下面是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 }
View Code

裝飾模式(Decorator),動態地給一個對象添加一些額外的職責,就增長功能來講,裝飾模式比生成子類更加靈活。

總結:這個例子中,每個類都形式本身的功能。他們公有的功能都寫在了父類。能夠實現動態的添加更多的衣服。

相關文章
相關標籤/搜索