Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

Design Pattern

  • Login to see the comments

  • Be the first to like this

Design Pattern

  1. 1. 淺談 Design Pattern Martin Chen
  2. 2. 大綱 <ul><li>前言 </li></ul><ul><li>Facade Pattern </li></ul><ul><li>Factory/Strategy Pattern </li></ul><ul><li>Adapter Pattern </li></ul><ul><li>討論 </li></ul>
  3. 3. 3-tier Application <ul><li>Presentation Tier </li></ul><ul><li>Business Logical Tier </li></ul><ul><li>Data Access Tier </li></ul>Presentation Business Logical Data Access
  4. 4. 前言 <ul><li>易維護 , 易擴充 , 跨平台設計理念 . </li></ul><ul><li>依不同屬性使用不同設計樣式 (Design Pattern). </li></ul><ul><li>一個系統可以使用多種設計樣式 . </li></ul>
  5. 5. <ul><li>'WRITTEN BY I20587 </li></ul><ul><li>DIM TABLE_TYPE,KEY_YEAR,KEY_MONTH,KEY_WEEK,SQL_YEAR </li></ul><ul><li>DIM PERIOD,MSG,FROM_YEAR,FROM_MONTH,FROM_DAY,TO_YEAR,TO_MONTH,TO_DAY </li></ul><ul><li>……… .. </li></ul><ul><ul><li>DIM RS,CN,SQL </li></ul></ul><ul><li>SET CN=SERVER.CREATEOBJECT(&quot;ADODB.CONNECTION&quot;) </li></ul><ul><li>SET RS=SERVER.CREATEOBJECT(&quot;ADODB.RECORDSET&quot;) </li></ul><ul><li>Const UDBDSN = &quot;DSN=DBCSC;uid=NTUSER;pwd=WINNER;&quot; </li></ul><ul><li>CN.OPEN UDBDSN </li></ul><ul><li>TABLE_TYPE=Request.Form(&quot;TABLE_TYPE&quot;) </li></ul><ul><li>P_REPORT=Request.Form(&quot;P_REPORT&quot;) </li></ul><ul><li>KEY_YEAR=trim(Request.Form(&quot;KEY_YEAR&quot;)) </li></ul><ul><li>……………………………… .. </li></ul><ul><li>'1. 先找週次定義檔,一週、一週往前找,直到有資料為止 </li></ul><ul><li>'RESPONSE.WRITE &quot;HERE&quot; </li></ul><ul><li>SQL=&quot;SELECT * FROM UP.TBUPWK order by YEAR_UPWK DESC,MONTH_UPWK desc,WEEK_UPWK desc&quot; </li></ul><ul><li>'RESPONSE.WRITE SQL </li></ul><ul><li>rs.open sql,cn </li></ul><ul><li>do while not rs.eof </li></ul><ul><li>SQL=&quot;SELECT DATE_W13 FROM UP.TBUPW13 WHERE DATE_W13 BETWEEN '&quot; & RS(&quot;FROM_YEAR_UPWK&quot;) &_ </li></ul><ul><li>RS(&quot;FROM_MONTH_UPWK&quot;) & RS(&quot;FROM_DAY_UPWK&quot;) & &quot;' AND '&quot; & RS(&quot;TO_YEAR_UPWK&quot;) & RS(&quot;TO_MONTH_UPWK&quot;) & RS(&quot;TO_DAY_UPWK&quot;) &&quot;'&quot; </li></ul><ul><li>rs2.open sql,cn </li></ul><ul><li>if not rs2.eof then </li></ul><ul><li>…… . </li></ul>
  6. 6. Facade ( 門面 ) Pattern <ul><li>是物件的結構樣式 </li></ul><ul><li>外部與一個子系統 通信 (Communication) 所必須通過的一個門面物件 . </li></ul>
  7. 9. <ul><li>當客戶端希望執行資料庫查詢時,只要將組成的指令傳送給 ExecuteCommand 這個函式,其餘內部的 Connection 與 Command 物件的建立與實際的執行就交由 DataAccessObject 去代為處理,簡化了客戶端原本需要自行撰寫的程序。 </li></ul><ul><li>Facade 的目的 </li></ul><ul><ul><li>就是將複雜的介面簡化。 </li></ul></ul><ul><ul><li>將複雜與瑣碎的步驟封裝起來。 </li></ul></ul><ul><ul><li>對外開放簡單的介面,讓客戶端能夠藉由呼叫簡單的介面而完成原本複雜的程式演算。 </li></ul></ul><ul><li>好處 </li></ul><ul><ul><li>資料儲存裝置與系統平台變異,易抽離系統核心的商業邏輯,系統本身的影響能夠降到最低。 </li></ul></ul><ul><ul><li>商業邏輯的再利用性也因此提高。 </li></ul></ul><ul><ul><li>團隊分工的工作分派。 </li></ul></ul><ul><li>設計 Data Access Layer 的方式就是一種 Facade Pattern 的實作。 </li></ul>
  8. 11. Factory Pattern , Strategy Pattern <ul><li>Factory Method Pattern 是類別的建構型樣式 , 又叫虛擬建構方法樣式或者多型性工廠 . </li></ul><ul><li>Strategy Pattern 屬於物件的行為樣式 , 又稱政策 (Policy) 樣式 . 準備一組演算法 , 並將每一組演算法封裝到一個獨立的具體類別中 ; 這些具體類別具有共同的介面 , 在不影響使用端 , 從而使得它們可以互換 . </li></ul>
  9. 12. <ul><li>假設今天老闆要我們設計一個銷售系統,我們打算將銷售系統中的 Data Access Layer 抽離出來,我們需要考量下面的因素: </li></ul><ul><ul><li>日後這個銷售系統可能搭配 SQL Server 或者 Access 甚至其他的儲存裝置來販售,所以我們必須將 Data Access Layer 的彈性與擴充性功能考量進去。 </li></ul></ul><ul><ul><li>我們在程式中使用到這個套件的時候,最好可以不知道我們現在是聯結到 SQL 還是 Access 的裝置上,那麼日後就只要變更 Data Access 的套件,高階的商業邏輯套件可以原封不動。 </li></ul></ul>
  10. 13. 傳統寫法
  11. 15. <ul><li>看起來這樣做是沒什麼問題的,我們只要依此類推,再增加 DataSet 、 DataReader 、 Scalar 等回傳型態的函式,然後功能依照平台的不同導到各自負責的函式去處理就好了。 </li></ul><ul><li>但是,要是增加了ㄧ個平台呢?比如說是用 Oracle 呢 ? </li></ul><ul><ul><li>那我們只好回去打開這顆套件,然後加上負責處理 Oracle 的函式以及在負責分派的四個函式加上屬於 Oracle 的分。 </li></ul></ul><ul><ul><li>每增加一個平台選項時必須異動到的地方有八處,如果這顆元件功能再強化一些細節的功能的話,只會更複雜而以。 </li></ul></ul><ul><ul><li>萬一衍生的種類來個十項,這支程式大概要又臭又長又難維護了…… </li></ul></ul>
  12. 16. 套用 Pattern <ul><li>我們設計了ㄧ個 Icommand 的介面,定義了執行資料庫的幾個函式與屬性,然後讓其他類別去實做它。我們可以選擇先實做負責處裡 SQL 平台的物件,因為這是我們的老闆要我們先出這個版本的產品。 </li></ul><ul><li>在 SOLCommand 類別裡,我們才真正實做了幾個處理 SQL 資料庫工作的函式。接下來如果我們要實做處理 Access 的類別時,只要新增一個類別 OleDBCommand 然後實做 Icommand 介面就好。 </li></ul>
  13. 18. <ul><li>不管我要增加幾個衍生的平台,都不會有機會去碰觸到已經寫好的程式碼,我們都知道,當系統隨著時間增長,會藏下許多我們都不知道的地雷,所以能夠不去修改到舊有的程式碼是最理想的,上面的做法可以滿足這樣的需求。 </li></ul><ul><li>接下來我們有另一個課題要解決,就是不讓客戶端知道最後實做的到底是那個平台的類別,對使用這顆物件的客戶端程式碼來說,它面對的永遠都只是 Icommand 介面。 </li></ul>
  14. 21. <ul><li>如同上面的範例,對客戶端來說,將永遠不會知道究竟是使用了哪種資料庫物件,它面對的只有一個類別跟一個介面, CommandFactory 與 Icommand ,不論後面究竟已經衍生了幾百種類別。換句話說,我們可以在客戶端程式不知情的情況下擴充甚至更換掉商業邏輯的元件,是不是很棒呢? </li></ul><ul><li>這樣的做法特別適用於企業邏輯時常需要的更換或擴充的系統,那麼就可以在不變動到舊有程式下達到擴充的目的。 </li></ul><ul><li>在這個例子中, Factory 指的自然就是負責建立符合實作介面的 CommandFactory ,而 Strategy 指的是利用客戶端只相依於一抽象介面的特性下,達到彈性替換演算法的功能。 </li></ul>
  15. 22. Adapter( 轉接器 ) Pattern <ul><li>當系統更換圖表產生元件時 ? </li></ul><ul><li>應該把舊有的程式碼全部改寫 ? </li></ul><ul><li>還是寫個轉接器把舊有系統跟新元件銜接上即可 ? </li></ul>
  16. 23. 舊系統  新系統
  17. 24. 原理解釋 <ul><li>舊 </li></ul><ul><ul><li>Dim Graphic as ChartOperation = new PieChartOperation() </li></ul></ul><ul><li>新 </li></ul><ul><ul><li>Dim Graphic as ChartOperation = new Adapter() </li></ul></ul><ul><ul><li>Adapter.DrawPieChart() call NewPieChartOpertion.Draw_A_PieChart() </li></ul></ul><ul><ul><li>Graphic.DrawPieChart() ==NewPieChartOpertion.Draw_A_PieChart() </li></ul></ul>
  18. 25. 結論 <ul><li>經由一個轉接器類別來作為 既有程式之間溝通的橋樑 ,這樣的架構我們稱之為轉接器樣式( Adapter Pattern )。在現實的世界中,當然會面對更複雜的問題,那麼轉接器的程式碼也就相對的會複雜的多,但是 都比起直接修改舊有程式碼要來得好 。 </li></ul><ul><li>日後這顆繪圖元件若是需要再進行更動時,我們只需要 調整轉接器類別 即可。 </li></ul><ul><li>符合物件導向設計原則中的封閉開放原則,既有的程式碼封裝起來,易於變動的程式碼與其抽離,盡量做到兩者之間不互相干涉。進而便達到物件導向的 易於維護與擴充的優點 。 </li></ul>
  19. 26. 討論

×