Design Pattern

26
淺淺 淺淺 Design Pattern Design Pattern Martin Chen Martin Chen

description

 

Transcript of Design Pattern

Page 1: Design Pattern

淺談 淺談 Design PatternDesign Pattern

Martin ChenMartin Chen

Page 2: Design Pattern

大綱大綱 前言前言 Facade PatternFacade Pattern Factory/Strategy PatternFactory/Strategy Pattern Adapter PatternAdapter Pattern 討論討論

Page 3: Design Pattern

3-tier Application3-tier Application

Presentation TierPresentation Tier Business Logical TierBusiness Logical Tier Data Access TierData Access Tier

Presentation Business Logical

Data Access

Page 4: Design Pattern

前言前言 易維護易維護 , , 易擴充易擴充 , , 跨平台設計理念跨平台設計理念 .. 依不同屬性使用不同設計樣式依不同屬性使用不同設計樣式 (Design Patt(Design Patt

ern).ern). 一個系統可以使用多種設計樣式一個系統可以使用多種設計樣式 ..

Page 5: Design Pattern

'WRITTEN BY I20587'WRITTEN BY I20587 DIM TABLE_TYPE,KEY_YEAR,KEY_MONTH,KEY_WEEK,SQL_YEARDIM TABLE_TYPE,KEY_YEAR,KEY_MONTH,KEY_WEEK,SQL_YEAR DIM PERIOD,MSG,FROM_YEAR,FROM_MONTH,FROM_DAY,TO_YEAR,TO_MONTH,TO_DAYDIM PERIOD,MSG,FROM_YEAR,FROM_MONTH,FROM_DAY,TO_YEAR,TO_MONTH,TO_DAY ……… ………....

DIM RS,CN,SQLDIM RS,CN,SQL SET CN=SERVER.CREATEOBJECT("ADODB.CONNECTION")SET CN=SERVER.CREATEOBJECT("ADODB.CONNECTION") SET RS=SERVER.CREATEOBJECT("ADODB.RECORDSET")SET RS=SERVER.CREATEOBJECT("ADODB.RECORDSET") Const UDBDSN = "DSN=DBCSC;uid=NTUSER;pwd=WINNER;"Const UDBDSN = "DSN=DBCSC;uid=NTUSER;pwd=WINNER;" CN.OPEN UDBDSNCN.OPEN UDBDSN TABLE_TYPE=Request.Form("TABLE_TYPE")TABLE_TYPE=Request.Form("TABLE_TYPE") P_REPORT=Request.Form("P_REPORT")P_REPORT=Request.Form("P_REPORT") KEY_YEAR=trim(Request.Form("KEY_YEAR"))KEY_YEAR=trim(Request.Form("KEY_YEAR")) ……………………………………………………………….... '1.'1. 先找週次定義檔,一週、一週往前找,直到有資料為止先找週次定義檔,一週、一週往前找,直到有資料為止 'RESPONSE.WRITE "HERE"'RESPONSE.WRITE "HERE" SQL="SELECT * FROM UP.TBUPWK order by YEAR_UPWK DESC,MONTH_UPWK desc,WEEK_UPWK desc"SQL="SELECT * FROM UP.TBUPWK order by YEAR_UPWK DESC,MONTH_UPWK desc,WEEK_UPWK desc" 'RESPONSE.WRITE SQL 'RESPONSE.WRITE SQL rs.open sql,cnrs.open sql,cn do while not rs.eof do while not rs.eof SQL="SELECT DATE_W13 FROM UP.TBUPW13 WHERE DATE_W13 BETWEEN '" & RS("FROM_YEAR_UPWSQL="SELECT DATE_W13 FROM UP.TBUPW13 WHERE DATE_W13 BETWEEN '" & RS("FROM_YEAR_UPW

K") &_K") &_ RS("FROM_MONTH_UPWK") & RS("FROM_DAY_UPWK") & "' AND '" & RS("TO_YEAR_UPWK") & RS("FROM_MONTH_UPWK") & RS("FROM_DAY_UPWK") & "' AND '" & RS("TO_YEAR_UPWK") & RSRS

("TO_MONTH_UPWK") & RS("TO_DAY_UPWK") &"'" ("TO_MONTH_UPWK") & RS("TO_DAY_UPWK") &"'" rs2.open sql,cnrs2.open sql,cn if not rs2.eof thenif not rs2.eof then …………..

Page 6: Design Pattern

Facade (Facade ( 門面門面 ) Pattern) Pattern

是物件的結構樣式是物件的結構樣式 外部與一個子系統外部與一個子系統通信通信 (Communication)(Communication)

所必須通過的一個門面物件所必須通過的一個門面物件 ..

Page 7: Design Pattern
Page 8: Design Pattern
Page 9: Design Pattern

當客戶端希望執行資料庫查詢時,只要將組成的指令傳送給當客戶端希望執行資料庫查詢時,只要將組成的指令傳送給 ExecuteExecuteCommandCommand 這個函式,其餘內部的這個函式,其餘內部的 ConnectionConnection 與與 CommandCommand 物件物件的建立與實際的執行就交由的建立與實際的執行就交由 DataAccessObjectDataAccessObject 去代為處理,簡化了去代為處理,簡化了客戶端原本需要自行撰寫的程序。客戶端原本需要自行撰寫的程序。

FacadeFacade 的目的的目的– 就是將複雜的介面簡化。就是將複雜的介面簡化。– 將複雜與瑣碎的步驟封裝起來。將複雜與瑣碎的步驟封裝起來。– 對外開放簡單的介面,讓客戶端能夠藉由呼叫簡單的介面而完成原本複對外開放簡單的介面,讓客戶端能夠藉由呼叫簡單的介面而完成原本複

雜的程式演算。雜的程式演算。 好處 好處

– 資料儲存裝置與系統平台變異,易抽離系統核心的商業邏輯,系統本身資料儲存裝置與系統平台變異,易抽離系統核心的商業邏輯,系統本身的影響能夠降到最低。的影響能夠降到最低。

– 商業邏輯的再利用性也因此提高。商業邏輯的再利用性也因此提高。– 團隊分工的工作分派。團隊分工的工作分派。

設計設計 Data Access LayerData Access Layer 的方式就是一種的方式就是一種 Facade PatternFacade Pattern 的實作。的實作。

Page 10: Design Pattern
Page 11: Design Pattern

Factory Pattern , Strategy Pattern Factory Pattern , Strategy Pattern

Factory Method Pattern Factory Method Pattern 是類別的建構型是類別的建構型樣式樣式 , , 又叫虛擬建構方法樣式或者多型性又叫虛擬建構方法樣式或者多型性工廠工廠 ..

Strategy PatternStrategy Pattern 屬於物件的行為樣式屬於物件的行為樣式 ,, 又又稱政策稱政策 (Policy)(Policy) 樣式樣式 . . 準備一組演算法準備一組演算法 , , 並將每一組演算法封裝到一個獨立的具體並將每一組演算法封裝到一個獨立的具體類別中類別中 ;; 這些具體類別具有共同的介面這些具體類別具有共同的介面 , , 在在不影響使用端不影響使用端 , , 從而使得它們可以互換從而使得它們可以互換 . .

Page 12: Design Pattern

假設今天老闆要我們設計一個銷售系統,假設今天老闆要我們設計一個銷售系統,我們打算將銷售系統中的我們打算將銷售系統中的 Data Access LayData Access Layerer 抽離出來,我們需要考量下面的因素: 抽離出來,我們需要考量下面的因素: – 日後這個銷售系統可能搭配日後這個銷售系統可能搭配 SQL ServerSQL Server或者或者 AA

ccessccess甚至其他的儲存裝置來販售,所以我們甚至其他的儲存裝置來販售,所以我們必須將必須將 Data Access LayerData Access Layer 的彈性與擴充性功的彈性與擴充性功能考量進去。能考量進去。

– 我們在程式中使用到這個套件的時候,最好可我們在程式中使用到這個套件的時候,最好可以不知道我們現在是聯結到以不知道我們現在是聯結到 SQLSQL還是還是 AccessAccess的裝置上,那麼日後就只要變更的裝置上,那麼日後就只要變更 Data AccessData Access的套件,高階的商業邏輯套件可以原封不動。 的套件,高階的商業邏輯套件可以原封不動。

Page 13: Design Pattern

傳統寫法傳統寫法

Page 14: Design Pattern
Page 15: Design Pattern

看起來這樣做是沒什麼問題的,我們只要依此類看起來這樣做是沒什麼問題的,我們只要依此類推,再增加推,再增加 DataSetDataSet 、、 DataReaderDataReader 、、 ScalarScalar等等回傳型態的函式,然後功能依照平台的不同導到回傳型態的函式,然後功能依照平台的不同導到各自負責的函式去處理就好了。各自負責的函式去處理就好了。

但是,要是增加了ㄧ個平台呢?比如說是用但是,要是增加了ㄧ個平台呢?比如說是用 OracOraclele呢呢 ??– 那我們只好回去打開這顆套件,然後加上負責處理那我們只好回去打開這顆套件,然後加上負責處理 OraOra

clecle 的函式以及在負責分派的四個函式加上屬於的函式以及在負責分派的四個函式加上屬於 OracleOracle的分。的分。

– 每增加一個平台選項時必須異動到的地方有八處,如每增加一個平台選項時必須異動到的地方有八處,如果這顆元件功能再強化一些細節的功能的話,只會更果這顆元件功能再強化一些細節的功能的話,只會更複雜而以。 複雜而以。

– 萬一衍生的種類來個十項,這支程式大概要又臭又長萬一衍生的種類來個十項,這支程式大概要又臭又長又難維護了…… 又難維護了……

Page 16: Design Pattern

套用套用 PatternPattern

我們設計了ㄧ個我們設計了ㄧ個 IcommandIcommand 的介面,定義了執行的介面,定義了執行資料庫的幾個函式與屬性,然後讓其他類別去實資料庫的幾個函式與屬性,然後讓其他類別去實做它。我們可以選擇先實做負責處裡做它。我們可以選擇先實做負責處裡 SQLSQL 平台的平台的物件,因為這是我們的老闆要我們先出這個版本物件,因為這是我們的老闆要我們先出這個版本的產品。 的產品。

在在 SOLCommandSOLCommand 類別裡,我們才真正實做了幾類別裡,我們才真正實做了幾個處理個處理 SQLSQL 資料庫工作的函式。接下來如果我們資料庫工作的函式。接下來如果我們要實做處理要實做處理 AccessAccess 的類別時,只要新增一個類別的類別時,只要新增一個類別OleDBCommandOleDBCommand然後實做然後實做 IcommandIcommand 介面就好。介面就好。

Page 17: Design Pattern
Page 18: Design Pattern

不管我要增加幾個衍生的平台,都不會有不管我要增加幾個衍生的平台,都不會有機會去碰觸到已經寫好的程式碼,我們都機會去碰觸到已經寫好的程式碼,我們都知道,當系統隨著時間增長,會藏下許多知道,當系統隨著時間增長,會藏下許多我們都不知道的地雷,所以能夠不去修改我們都不知道的地雷,所以能夠不去修改到舊有的程式碼是最理想的,上面的做法到舊有的程式碼是最理想的,上面的做法可以滿足這樣的需求。 可以滿足這樣的需求。

接下來我們有另一個課題要解決,就是不接下來我們有另一個課題要解決,就是不讓客戶端知道最後實做的到底是那個平台讓客戶端知道最後實做的到底是那個平台的類別,對使用這顆物件的客戶端程式碼的類別,對使用這顆物件的客戶端程式碼來說,它面對的永遠都只是來說,它面對的永遠都只是 IcommandIcommand 介介面。面。

Page 19: Design Pattern
Page 20: Design Pattern
Page 21: Design Pattern

如同上面的範例,對客戶端來說,將永遠不會知如同上面的範例,對客戶端來說,將永遠不會知道究竟是使用了哪種資料庫物件,它面對的只有道究竟是使用了哪種資料庫物件,它面對的只有一個類別跟一個介面,一個類別跟一個介面, CommandFactoryCommandFactory 與與 IcoIcommandmmand ,不論後面究竟已經衍生了幾百種類別。,不論後面究竟已經衍生了幾百種類別。換句話說,我們可以在客戶端程式不知情的情況換句話說,我們可以在客戶端程式不知情的情況下擴充甚至更換掉商業邏輯的元件,是不是很棒下擴充甚至更換掉商業邏輯的元件,是不是很棒呢? 呢?

這樣的做法特別適用於企業邏輯時常需要的更換這樣的做法特別適用於企業邏輯時常需要的更換或擴充的系統,那麼就可以在不變動到舊有程式或擴充的系統,那麼就可以在不變動到舊有程式下達到擴充的目的。 下達到擴充的目的。

在這個例子中,在這個例子中, FactoryFactory 指的自然就是負責建立指的自然就是負責建立符合實作介面的符合實作介面的 CommandFactoryCommandFactory ,而,而 StrategStrategyy 指的是利用客戶端只相依於一抽象介面的特性指的是利用客戶端只相依於一抽象介面的特性下,達到彈性替換演算法的功能。下,達到彈性替換演算法的功能。

Page 22: Design Pattern

Adapter(Adapter( 轉接器轉接器 ) Pattern) Pattern

當系統更換圖表產生元件時 當系統更換圖表產生元件時 ??應該把舊有的程式碼全部改寫 應該把舊有的程式碼全部改寫 ??還是寫個轉接器把舊有系統跟新元件銜接還是寫個轉接器把舊有系統跟新元件銜接上即可 上即可 ? ?

Page 23: Design Pattern

舊系統

新系統

Page 24: Design Pattern

原理解釋原理解釋 舊舊

– Dim Graphic as ChartOperation = new PieChartOpeDim Graphic as ChartOperation = new PieChartOperation()ration()

新新– Dim Graphic as ChartOperation = new Adapter()Dim Graphic as ChartOperation = new Adapter()– Adapter.DrawPieChart() call NewPieChartOpertion.Adapter.DrawPieChart() call NewPieChartOpertion.

Draw_A_PieChart()Draw_A_PieChart()– Graphic.DrawPieChart() ==NewPieChartOpertion.DGraphic.DrawPieChart() ==NewPieChartOpertion.D

raw_A_PieChart()raw_A_PieChart()

Page 25: Design Pattern

結論結論 經由一個轉接器類別來作為經由一個轉接器類別來作為既有程式之間溝通的既有程式之間溝通的橋樑橋樑,這樣的架構我們稱之為轉接器樣式(,這樣的架構我們稱之為轉接器樣式( AdaAdapter Patternpter Pattern)。在現實的世界中,當然會面對)。在現實的世界中,當然會面對更複雜的問題,那麼轉接器的程式碼也就相對的更複雜的問題,那麼轉接器的程式碼也就相對的會複雜的多,但是會複雜的多,但是都比起直接修改舊有程式碼要都比起直接修改舊有程式碼要來得好來得好。 。

日後這顆繪圖元件若是需要再進行更動時,我們日後這顆繪圖元件若是需要再進行更動時,我們只需要只需要調整轉接器類別調整轉接器類別即可。即可。

符合物件導向設計原則中的封閉開放原則,既有符合物件導向設計原則中的封閉開放原則,既有的程式碼封裝起來,易於變動的程式碼與其抽離,的程式碼封裝起來,易於變動的程式碼與其抽離,盡量做到兩者之間不互相干涉。進而便達到物件盡量做到兩者之間不互相干涉。進而便達到物件導向的導向的易於維護與擴充的優點易於維護與擴充的優點。。

Page 26: Design Pattern

討論討論