文章出處

前言

設計模式目錄:

本篇目錄:

  前段時間在亞馬遜買了一本《CLR》的書,當時搞活動買一送一,然后挑了一本《漫談設計模式》,一位不相識的大牛寫的,這幾天閑來無事,翻了幾頁瞧了瞧,感覺還是不錯的,正好小菜也一直想學習設計模式,就決定認真的拜讀下。

  小菜寫博文的目的是整理自己所整理的知識,小菜是一個喜歡收集的人,好的東西我都喜歡收藏起來,但是寫出來就是另一回事了,一是鍛煉自己的表達能力及回味所學的知識,而是分享給需要幫助的人。

  另外Tony Zhao寫的【原】從頭學習設計模式感覺還是不錯,淺顯易懂,很適合初學者。

對象和模式

  雖然一直是用的面向對象的語言,說實話,小菜真的沒有更深層次的了解對象的概念,只能慢慢積累了,其實如果我們不從編程的角度去看待編程,就會發現其實編程只是和普通的解決方案一樣,就像買火車票,去售票廳可以買,在網上可以買,那編程實現的就是網上買票的這個過程,和其他方式實現的效果都是一樣把票買到,只是過程不是一樣。在這本書里面,作者詳細說了下模式(Pattern)的簡史,最開始,模式是在建筑行業提出并運用的,到了后來,由Gof四人幫把模式設計引入到編程世界,并收編了23個最常用的設計模式,得以慢慢發展壯大。

  模式定義如下:模式是某上下文環境中一個問題的解決方案。

  但是我更喜歡作者的定義:模式是某上下文環境中一個問題的“常用”解決方案。

  常用并正確的模式才可以算上真正的模式,用鑰匙開門和用錘子撬門都可以進入房子,但是用錘子撬門進入房子并不成為一種模式。

  GoF為模式定義了4個基本要素:

  •  模式名稱(Pattern name)
  •  問題(Problem)
  •  解決方案(Solution)
  •  效果(Consequence)

模板方法模式-從回家過年說起

  馬上就要過年了,大家都很期待,回家的方式有很多種,汽車,火車,船,飛機等,不管什么方式回家,回家過春節就三個過程:買票、回家和家里慶祝。

  比如坐火車回家就可以這些寫:

1     public class HapplyPeopleByHuoChe
2     {
3         public void celebrateSpring()
4         {
5             Console.WriteLine("買票....");
6             Console.WriteLine("坐火車....");
7             Console.WriteLine("回家慶祝....");
8         }
9     }
View Code

  但是有的人需要坐火車,有的人需要坐汽車回家,那我們復制+粘貼修改下:

1     public class HapplyPeopleByQiChe
2     {
3         public void celebrateSpring()
4         {
5             Console.WriteLine("買票....");
6             Console.WriteLine("坐汽車....");
7             Console.WriteLine("回家慶祝....");
8         }
9     }
View Code

  這樣我們就會發現問題,增加一種交通工具,我們就要復制+粘貼下,這樣代碼就會變得難以維護和開發,針對這種情況,作者提出了一種原則:DRY(Don'T Repeat Yourself,不要復復制你自己),至于這種原則的好與壞我就不闡述了,上面我們那種實現方式的問題其實就是代碼重用,下面說下模板方法模式的運用。

使用繼承

  防止代碼重用,OOP的一大特性就是繼承,既然都是買票、回家和在家慶祝,那我們可以把這三種方式抽象出來,代碼如下:

 1     public abstract class HapplyPeople2
 2     {
 3         protected void BuyTicket()
 4         {
 5             Console.WriteLine("買票....");
 6         }
 7         protected abstract void Travel()
 8         {
 9             //待重寫
10         }
11         protected void Happy()
12         {
13             Console.WriteLine("回家慶祝....");
14         }
15     }
View Code

  因為交通方式不同,我們只需要把Travel方法抽象就可以,這樣抽象類的實現類就必須去實現Travel這個抽象方法,而不需要去實現其他的方法。坐火車我們就可以這樣實現:

1     public class HapplyPeopleByHuoChe:HapplyPeople2
2     {
3         protected override void Travel()
4         {
5             Console.WriteLine("坐火車回家....");
6         }
7     }
View Code

  相類似的,坐飛機:

1     public class HapplyPeopleByAir : HapplyPeople2
2     {
3         protected override void Travel()
4         {
5             Console.WriteLine("坐飛機回家....");
6         }
7     }
View Code

  在上面的例子中HapplyPeople2這個類就是模板,其實在開發一些別的東西的時候我們有時候也會用到Template,比如做一些CMS(內容管理系統)的時候,因為就那幾個頁面,只是頁面的樣式會有所不同,不同的系統還好,如果一個系統用不同的頁面樣式就比較難辦了,這時候就可以用到Template,如下:

  

  里面是一些通過自定義的模板語言創建的模板頁面,生成的時候會轉化為相應的代碼,這樣我們就可以一個系統擁有不同的樣式,只需要在后臺切換下,非常方便。

  其實慢慢就會發現模式會運用到任何地方,只要你細心觀察,它就在你身邊。

引入回調

  言歸正傳,我們使用模板方法發現有很多好處,比如代碼重用、易于擴展、解決代碼冗余問題等,但是當子類變得越多的時候,就會變得那么不容易維護了。比如我們查詢數據庫的信息:

  1.  連接Connection對象
  2.  執行查詢語句
  3.  處理查詢的結果并分析返回結果

  通過上面的需求我們就可以發現1和2都是一樣的,只是返回結果處理的方式不同,回調不同語言有不同的實現方式,C語言使用函數指針實現,java使用內部匿名類實現,C#使用委托(delegate)實現,因為作者整本書都是用java寫的,我電腦沒裝java環境,那就用我們熟悉的C#實現了。

  代碼如下:

 1     /// <summary>
 2     /// 數據庫操作類
 3     /// </summary>
 4     public class DbHelperOra
 5     {
 6         public static bool Query(string SQLString, TestTemplete.CallBackDG<DataSet> cb)
 7         {
 8             using (OracleConnection connection = new OracleConnection(""))
 9             {
10                 try
11                 {
12                     //connection.Open();
13                     //OracleDataAdapter command = new OracleDataAdapter(SQLString, connection);
14                     DataSet ds = new DataSet();
15                     //command.Fill(ds, "ds");
16                     return cb(ds);
17                 }
18                 catch (System.Data.OracleClient.OracleException E)
19                 {
20                     connection.Close();
21                     throw new Exception(E.Message);
22                 }
23             }
24         }
25     }
View Code
 1     /// <summary>
 2     /// 測試
 3     /// </summary>
 4     public class TestTemplete
 5     {
 6         public delegate bool CallBackDG<T>(T param);
 7         public bool Test()
 8         {
 9             return DbHelperOra.Query("testSql", new CallBackDG<DataSet>(CallBackF));
10         }
11         public bool CallBackF(DataSet ds)
12         {
13             if (ds.Tables.Count==0 )
14             {
15                 return false;
16             }
17             if (ds.Tables[0].Rows.Count > 0)
18             {
19                 return true;
20             }
21             else
22             {
23                 return false;
24             }
25         }
26     }
View Code

  示例代碼下載:TempleteMethod.rar

后記

  騷年們,和小菜一起整理學習吧,未完待續。。。

 


文章列表




Avast logo

Avast 防毒軟體已檢查此封電子郵件的病毒。
www.avast.com


arrow
arrow
    全站熱搜
    創作者介紹
    創作者 大師兄 的頭像
    大師兄

    IT工程師數位筆記本

    大師兄 發表在 痞客邦 留言(0) 人氣()