?? factory with .net(design pattern).txt
字號:
Factory with .NET(Design Pattern)
http://www.shecn.com/best/g14/g840.htm
顧名思意﹐樣式是人們遭遇到特定問題時﹐大家慣用的應付方式。樣式可用來解決問題﹐而且是有效、可靠的。掌握愈多樣式﹐運用愈成熟﹐就愈是傑出的設計專家。
依據樣式理論大師亞歷山大(Christopher Alexander) 之定義﹕
「樣式是某外在環境(Context) 下﹐對特定問題(Problem)的
慣用解決之道(Solution)」
例如﹐在平坦的校園裡(Context) ﹐下述兩項需求是互相衝突的﹕
◎學生需要交通工具代步。
◎校園空氣必須保持清潔。
就產生問題(Problem) 了﹐該如何化解呢﹖在一般校園裡﹐慣用解決之道(Solution)是﹕規定在校園中只能騎自行車﹐不能騎有污染的機車和汽車。此解決之道是否有效﹐是取決於外在環境(Context) 。例如﹐在不平坦的清華大學校園中﹐上述解決之道就無效用了。於是另找解決方案來處理這問題了﹔例如﹐提供電動機車供學生在校園中使用。
自從1991年以來﹐亞歷山大的樣式理論逐漸應用於OO軟體的設計上﹐可解決軟體設計上的問題。例如﹐軟體設計時﹐常見下述問題﹕
◎ 為了提昇軟體的柔性和活力,軟體必須元件化。
◎ 軟體元件之間的相依性常太高﹐不易個別抽換元件﹐
軟體的「軟」性就降低了。
可利用樣式解決這種問題﹐求增強元件之間的獨立性﹐提高軟體的彈性(Flexibility) ﹐降低軟體的維護費用﹗為了解決類似的軟體設計問題,Erich Gamma等人合著的書籍﹕
"Design Patterns: Elements of Reusable Object-Oriented Software"
一書列出23種軟體設計樣式(Design Pattern)﹐可解決軟體設計上的特定問題。於此介紹Gamma的Factory樣式。首先拿個簡單程式來敘述「問題」之所在﹕
'ex01.bas
Imports System.ComponentModel
Imports System.Drawing
Imports System.WinForms
'----------------------------------------------------
Class Int
Private value As Integer
Public Sub New()
value = 100
End Sub
Public Sub DisplayValue()
MessageBox.Show("value = " + str(value))
End Sub
End Class
'-----------------------------------------------------------
Public Class Form1
Inherits System.WinForms.Form
Public Sub New()
MyBase.New()
Form1 = Me
'This call is required by the Win Form Designer.
InitializeComponent()
'TODO: Add any initialization after the InitializeComponent() call
End Sub
'Form overrides dispose to clean up the component list.
Public Overrides Sub Dispose()
MyBase.Dispose()
components.Dispose()
End Sub
#Region " Windows Form Designer generated code "
......
#End Region
Protected Sub Form1_Click(ByVal sender As Object, ByVal e As System.EventArgs)
Dim pi As Int
Pi = New Int()
pi.DisplayValue()
End Sub
End Class
此程式輸出:
value = 100
兩類別的相依性很高﹐原因是﹕Form1類別裡的指令-----
Dim pi As Int
Pi = New Int()
直接使用到Int字眼﹐且使用兩次。於是﹐問題是﹕
「若必須將Int類別名稱改為Float時﹐得更換Form1類別中的Int字眼」。
亦即﹐抽換Int類別時﹐會牽連到Form1類別﹐抽換過程將不會很順暢﹗藉由抽象類別﹐可解決部分問題﹕
'ex02.bas
Imports System.ComponentModel
Imports System.Drawing
Imports System.WinForms
'---------------------------------------------------------
Class Data
Public Overridable Sub DisplayValue()
End Sub
End Class
Class Int
Inherits Data
Private value As Integer
Public Sub New()
value = 100
End Sub
Public Overrides Sub DisplayValue()
MessageBox.Show("value = " + str(value))
End Sub
End Class
Public Class Form1
Inherits System.WinForms.Form
Public Sub New()
MyBase.New()
Form1 = Me
'This call is required by the Win Form Designer.
InitializeComponent()
'TODO: Add any initialization after the InitializeComponent() call
End Sub
'Form overrides dispose to clean up the component list.
Public Overrides Sub Dispose()
MyBase.Dispose()
components.Dispose()
End Sub
#Region " Windows Form Designer generated code "
......
#End Region
Protected Sub Form1_Click(ByVal sender As Object, ByVal e As System.EventArgs)
Dim pi As Data
pi = New Int()
pi.DisplayValue()
End Sub
End Class
此程式輸出:
value = 100
刪除掉1 個Int字眼﹐已長進些了﹐不是嗎﹖但問題尚未全部解決﹗Int字眼仍留在Form1類別內﹐還是難分難解﹗待會兒再來介紹如何解決這個難題,請先看看VB的Interface觀念能替代上述的抽象類別。例如,上述程式相當於:
'ex03.bas
Imports System.ComponentModel
Imports System.Drawing
Imports System.WinForms
'----------------------------------------------------
Interface IData
Sub DisplayValue()
End Interface
Class Int
Implements IData
Private value As Integer
Public Sub New()
value = 100
End Sub
Public Sub DisplayValue() Implements IData.DisplayValue
MessageBox.Show("value = " + str(value))
End Sub
End Class
'-----------------------------------------------------------
Public Class Form1
Inherits System.WinForms.Form
Public Sub New()
MyBase.New()
Form1 = Me
'This call is required by the Win Form Designer.
InitializeComponent()
'TODO: Add any initialization after the InitializeComponent() call
End Sub
'Form overrides dispose to clean up the component list.
Public Overrides Sub Dispose()
MyBase.Dispose()
components.Dispose()
End Sub
#Region " Windows Form Designer generated code "
......
#End Region
Protected Sub Form1_Click(ByVal sender As Object, ByVal e As System.EventArgs)
Dim pi As IData
pi = New Int()
pi.DisplayValue()
End Sub
End Class
使用Factory樣式可解決上述問題﹗它將New Int() 指令包裝(Encapsulate) 起來﹐Int字眼就不再出現於Form1類別中了。依照Erich Gamma 書中的Factory樣式﹐應定義一個Factory類別,將Form1與Int兩類別隔開來﹐令其互相獨立﹐以利於個別抽換。樣式好像馬路的安全島或分道欄。如下程式:
'ex04.bas
Imports System.ComponentModel
Imports System.Drawing
Imports System.WinForms
'----------------------------------------------------
Interface IData
Sub DisplayValue()
End Interface
Class Int
Implements IData
Private value As Integer
Public Sub New()
value = 100
End Sub
Public Sub DisplayValue() Implements IData.DisplayValue
MessageBox.Show("value = " + str(value))
End Sub
End Class
Class Factory
Public Function CreateDataObject() As IData
CreateDataObject = New Int()
End Function
End Class
'-----------------------------------------------------------
Public Class Form1
Inherits System.WinForms.Form
Public Sub New()
MyBase.New()
Form1 = Me
'This call is required by the Win Form Designer.
InitializeComponent()
'TODO: Add any initialization after the InitializeComponent() call
End Sub
'Form overrides dispose to clean up the component list.
Public Overrides Sub Dispose()
MyBase.Dispose()
components.Dispose()
End Sub
#Region " Windows Form Designer generated code "
......
#End Region
Protected Sub Form1_Click(ByVal sender As Object, ByVal e As System.EventArgs)
Dim pi As IData
Dim df As Factory
df = New Factory()
pi = df.CreateDataObject()
pi.DisplayValue()
End Sub
End Class
此程式輸出:
value = 100
利用Factory元件降低Form1與Int元件之間的相依性﹐令其互相獨立﹐就易於抽換。例如將Int類別更換為Real類別時,只需將Factory類別裡的指令更改如下:
Class Factory
Public Function CreateDataObject() As IData
CreateDataObject = New Real()
End Function
End Class
Form1類別裡的指令毫不受影響。前面曾經由Int而抽象出IData介面,提昇了一些彈性。所以也由Factory抽象出IFactory介面如下程式:
'ex05.bas
Imports System.ComponentModel
Imports System.Drawing
Imports System.WinForms
'----------------------------------------------------
Interface IData
Sub DisplayValue()
End Interface
Class Int
Implements IData
Private value As Integer
Public Sub New()
value = 100
End Sub
Public Sub DisplayValue() Implements IData.DisplayValue
MessageBox.Show("value = " + str(value))
End Sub
End Class
Interface IFactory
Function CreateDataObject() As Idata
End Interface
Class Factory
Implements IFactory
Public Function CreateDataObject() As IData
CreateDataObject = New Int()
End Function
End Class
'-----------------------------------------------------------
Public Class Form1
Inherits System.WinForms.Form
Public Sub New()
MyBase.New()
Form1 = Me
'This call is required by the Win Form Designer.
InitializeComponent()
'TODO: Add any initialization after the InitializeComponent() call
End Sub
'Form overrides dispose to clean up the component list.
Public Overrides Sub Dispose()
MyBase.Dispose()
components.Dispose()
End Sub
#Region " Windows Form Designer generated code "
......
#End Region
Protected Sub Form1_Click(ByVal sender As Object, ByVal e As System.EventArgs)
Dim pi As IData
Dim df As IFactory
df = New Factory()
pi = df.CreateDataObject()
pi.DisplayValue()
End Sub
End Class
此程式輸出:
value = 100
以此類推,也能從Form1抽像出介面,但是不僅抽出程序名稱而已,還有指令,所以應該以父類別(Superclass)來表達該抽象。還因為要避開多重繼承(Multiple Inheritance),所以就將繼承改由委託(Delegation)方式表達之。如下程式:
'ex06.bas
Imports System.ComponentModel
Imports System.Drawing
Imports System.WinForms
'----------------------------------------------------
Interface IData
Sub DisplayValue()
End Interface
Class Int
Implements IData
Private value As Integer
Public Sub New()
value = 100
End Sub
Public Sub DisplayValue() Implements IData.DisplayValue
MessageBox.Show("value = " + str(value))
End Sub
End Class
Interface IFactory
Function CreateDataObject() As Idata
End Interface
Class IntFactory
Implements IFactory
Public Function CreateDataObject() As IData
CreateDataObject = New Int()
End Function
End Class
'-----------------------------------------------------------
Class Document
Private pi As IData
Public Sub New(ByVal pf As IFactory)
pi = pf.CreateDataObject()
End Sub
Public Sub DisplayValue()
pi.DisplayValue()
End Sub
End Class
Public Class Form1
Inherits System.WinForms.Form
Public Sub New()
MyBase.New()
Form1 = Me
'This call is required by the Win Form Designer.
InitializeComponent()
'TODO: Add any initialization after the InitializeComponent() call
End Sub
'Form overrides dispose to clean up the component list.
Public Overrides Sub Dispose()
MyBase.Dispose()
components.Dispose()
End Sub
#Region " Windows Form Designer generated code "
......
#End Region
Protected Sub Form1_Click(ByVal sender As Object, ByVal e As System.EventArgs)
Dim d As Document
Dim df As IFactory
df = New IntFactory()
d = New Document(df)
d.DisplayValue()
End Sub
End Class
此程式輸出: value = 100
其中Form1_Click()程序的內容:
Dim d As Document
Dim df As IFactory
df = New IntFactory()
d = New Document(df)
d.DisplayValue()
就相當於:
Dim d As New Document(New IntFactory())
d.DisplayValue()
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -