VB.Net中文教程(13) Whole-Part關係 (轉)

worldblog發表於2007-12-04
VB.Net中文教程(13) Whole-Part關係 (轉)[@more@]

請注意 ......
著作權所有人:物澤事業股份有限公司、
  MISOO技術顧問團隊、物件導向雜誌作者、等。
u本摘自 物件導向雜誌、精通物件觀念與技術等書籍著作。
u本檔案僅供您的參閱,請遵守著作權法,不得做其它商業用途。


  主題:  Whole-Part關係


??????????  內容  ??????????
v 1. 物件Whole-Part關係
v 2. 組合/部分關係
v 3. 包含者/內容關係
v 4. 集合/成員關係

 

 

1. 物件Whole-Part關係

  類別繼承(Class inheritance)和物件組合( composition)是再使用(Reuse)的兩大法寶。類別繼承就是建立父、子類別之關係﹔例如﹐「學生」可分為「大學生」、「中學生」和「小學生」三類別﹐其繼承關係圖示如下﹕
 
  圖1、 以UML表達類別繼承

  物件組合的目的是﹕創造「複合物件」(Composite object)﹔例如﹐醫院內含醫師和護士等﹐其組合關係圖示如下﹕

 
  圖2、 以UML表達物件組合

繼承與組合兩大法寶能聯合使用﹐以組織龐大的軟體。例如﹐汽車分為客車、卡車、轎車等子類別﹐而且汽車內含引擎、車體、輪胎等零件﹐則此汽車系統圖示如下圖3和圖4﹕


 
  圖3、 汽車的類別繼承體系

 
  圖4、 汽車的物件組合關係

本節裡﹐將進一步分析與說明物件組合方法。尤頓(Yourdon) 認為﹐常見組合關係有三﹕
  1)  組合╱部分(Assembly-parts)關係。
  2)  包含╱內容(Container-contents)關係。
  3)  集合╱成員(Collection-members)關係。

 

 

2. 組合/部分關係

  組合/部分關係﹐常稱為APO(A part of)關係﹔例如﹐汽車是「組合」﹐其內含各零件是「部分」。門是房子的一部分﹐所以房子是「組合」﹐門是「部分」﹔此外﹐窗子也是房子的「部分」。這房子與門窗之關係﹐圖示如下﹕

 
  圖5、 房子的物件組合關係

以VB表達如下﹕

'ex01.bas
Imports System.ComponentModel
Imports System.Drawing
Imports System.s
'---------------------------------------------------------------------------------
Class House
  Class Door
  Public size As Double
  Public Sub New(ByVal s As Double)
  size = s
  End Sub
  End Class
 
  Class Window
  Public size As Double
  Public Sub New(ByVal s As Double)
  size = s
  End Sub
  End Class
 
  Private dr As Door
  Private win As Window
  Public Sub New()
  dr = New Door(50)
  win = New Window(100)
  End Sub
  Public Sub Show()
  Messagebox.Show("Door: " + str(dr.size) + "  Win: " + str(win.size))
  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 FoDesigner.
  InitializeComponent()
  'TODO: Add any initialization after the InitializeComponent() call
  End Sub
  'Form overrs dispose to clean up the component list.
  Public Overrides Sub Dispose()
  MyBase.Dispose()
  components.Dispose()
  End Sub
#Region " Form Designer generated code "
  ......
#End Region
  Protected Sub Form1_Click(ByVal sender As Object, ByVal
  e As System.EventArgs)
  Dim h As New House()
  h.Show()
  End Sub
End Class

以此輸出如下﹕
  Door: 50  Win: 100


House 之物件誕生後﹐立即誕生內含之Door物件和Window物件。例如﹐宣告指令──
  Dim h As New House()

此時﹐h 物件誕生了﹐其內含之dr 和win物件亦誕生了。

 

此h 通稱為「組合物件」(Composite object)﹐而dr 和win 則稱為「部分物件」(Component object)。這種關係具有一項特色﹕組合物件與部分物件的壽命應該是一致的。
  在邏輯(Logical)意義上,這House 結構中﹐門和窗隨著房子而具有「生死與共」之親蜜關係,也就是壽命一致。在計算機實體(Physical)表達時,House 之物件並不「真正」包含Door及Window之物件﹐只是利用兩個參考指向它們。所以上圖也可想象如下:

 
上述兩種實體結構皆表達了「組合/部分」關係。請再看個例子:

'ex02.bas
Imports System.ComponentModel
Imports System.Drawing
Imports System.WinForms
'----------------------------------------------------
Class Person
  Private p_name As String
  Private p_age As Integer
 
  Public Sub New(ByVal na As String, ByVal a As Integer)
  p_name = na
  p_age = a
  End Sub
  Public Function isEqual(ByVal obj As Person) As Integer
  Dim k As Integer = 0
  If Me.p_name = obj.p_name Then
  k = 1
  End If
  isEqual = k
  End Function
  Public Sub Show()
  Messagebox.Show(Me.p_name + ", " + str(Me.p_age))
  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 a As New Person("Alvin", 35)
  Dim b As New Person("David", 25)
  a.Show()
  b.Show()
  Messagebox.Show(str(a.isEqual(b)))
  Messagebox.Show(str(b.isEqual(New Person("David", 32))))
  End Sub
End Class

此程式輸出﹕
  Alvin, 35 
David, 25 

「組合」物件之建構者New()程式誕生「部分」物件。此a 、b 兩物件之內容為﹕

 


 

在isEqual()程式裡,兩個物件拿其p_name 值來比較。例如﹐a.p_name 值是"Alvin" ﹐而b.p_name 值是"David" ﹐所以a.isEqual(b)之值為0 (False)。

 

 

 

3. 包含者/內容關係

  上節的House 結構中﹐門和窗隨著房子而具有「生死與共」之親蜜關係。然而﹐日常生活中﹐常見類似但並不如此親蜜的情形。例如﹐飛行員坐于飛機駕駛倉內開飛機﹔司機在汽車內駕駛汽車﹔客人乘座於巴士內等等。司機不是汽車的零件﹐客人亦非巴士之﹐所以汽車與司機之間並非「組合/部分」關係﹔然而﹐汽車的確包含著司機﹐因之稱為「包含者/內容」(Container-contents)關係。
  司機和汽車為獨立之物件﹐不像引擎一直包含於汽車內﹔於駕駛汽車時﹐司機才被包含於汽車內。顯然地﹐司機與汽車之壽命不一樣長。「包含者/內容」關係是一種特殊的組合結構﹐其圖示方法與「組合/部分」關係相同。例如﹐

 
此圖表達了﹕
  ◎  汽車與引擎之間為「組合/部分」關係。
  ◎  汽車與司機之間為「包含者/內容」關係。

以VB表達如下﹕

'ex03.bas
Imports System.ComponentModel
Imports System.Drawing
Imports System.WinForms
'----------------------------------------------------
Class
  Private name As String
  Public Sub New(ByVal na As String)
  name = na
  End Sub
  Public Sub Show()
  MessageBox.Show("Driver: " + name)
  End Sub
End Class

Class Car
  Class Engine
  Public model As String
  Public Sub New(ByVal mdl As String)
  model = mdl
  End Sub
  End Class
 
  Private e As Engine
  Private dr As Driver
  Public Sub New()
  e = New Engine("Honda")
  End Sub
  Public Sub assignTo(ByVal d As Driver)
  dr = d
  End Sub
  Public Sub Show()
  MessageBox.Show("Engine: " + e.model)
  dr.Show()
  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 civic As New Car()
  Dim d1 As New Driver("Wang")
  Dim d2 As New Driver("Kao")
  civic.assignTo(d1)
  civic.Show()
  civic.assignTo(d2)
  civic.Show()
  End Sub
End Class

此程式輸出﹕
  Model: Honda
  Driver: Wang
  Model: Honda
  Model" Kao

Car之物件誕生後﹐也誕生Engine之物件e ﹔同時立即指定司機﹐如下指令﹕
 
  Dim civic As New Car()
  Dim d1 As New Driver("Wang")
  .....
  civic.assignTo(d1)
  .....

日常生活中的常見情況﹕汽車物件誕生時﹐不須立即指定司機物件。例如﹐汽車出廠時或閒置時並無司機﹐且汽車經常更換司機。此情形下﹐應先誕生civic物件和d1物件,如下:

 

此時,未立即指定司機﹔而必要時才以assignTo()程式指定司機。例如,將d1指定給civic物件﹐就令civic內之參考變數dr指向d1 物件,如下:

 

  上述程式裡,d1、d2及civic 物件之間﹐誰先誕生並無關緊要﹐各獨立存在。指令──civic.assignTo(d1) 將d1司機指定給civic 物件﹔另一指令──civic.assignTo(d2)表示﹕改由d2擔任civic 之司機。
  此Car 類別以參考變數e來指向Engine之物件。現在﹐茲拿上節的Person類別做為例子﹐如果某人(Person 之物件)結婚了﹐就有配偶﹔反之尚未結婚時﹐則無配偶。此時﹐應將Person類別之定義修改如下﹐以表達這種「配偶」關係﹕

'ex04.bas
Imports System.ComponentModel
Imports System.Drawing
Imports System.WinForms
'----------------------------------------------------
Class Person
  Private p_name As String
  Private p_age As Integer
  Private p_spouse As Person
 
  Public Sub New(ByVal na As String, ByVal a As Integer)
  p_name = na
  p_age = a
  End Sub
  Public Sub spouse(ByVal sp As Person)
  p_spouse = sp
  sp.p_spouse = Me
  End Sub
  Public Sub Show()
  Messagebox.Show(Me.p_name + ", " + str(Me.p_age)
  + ",  sp: " + Me.p_spouse.p_name)
  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 x As New Person("David", 32)
  Dim y As New Person("Hellen", 24)
  x.spouse(y)
  x.Show()
  y.Show()
  End Sub
End Class

此程式輸出﹕
David, 32, sp: Hellen
Hellen, 24, sp: David

  資料成員p_spouse指向配偶﹐而配偶亦為Person之物件。所以p_spouse之型態應為Person。一個人剛誕生時並無配偶﹐到結婚時才有配偶﹐所以藉spouce()來建立配偶關係。物件x 與y 結婚之後﹐互為對方之配偶。所以x.p_spouse指向y ﹐而y.p_spouse則指向x 。此時﹐x 和y 之內容如下﹕

 
 
於是這Person類別表達了「婚姻」關係。

 

 


4. 集合/成員關係

  集合意謂著「團體」(Group) ﹐由其成員(Member)組成的群體。例如﹐學校裡的社團內有團員﹔公司的銷售部含有推銷人員。這團體並不像汽車實際包含著司機﹐而只是其成員之集合而已。這情形﹐統稱為「集合/成員」(Collection-members)關係。
  有趣的是﹕在企業活動中﹐人們規劃的方案﹐含許多小方案﹔則大方案是由小方案所組成。例如﹐東北亞旅行團的行程表包括在日本的觀光行程、在韓國的觀光行程和在香港的觀光行程。這總行程表圖示如下﹕

 

  總行程是次行程(或稱段行程)之集合﹐這是「集合/成員」關係。

 

此外﹐棒球隊是由經理、教練和球員組成﹕訂單中含若干產品專案﹐皆為集合/成員關係。實際寫程式時﹐不需明確劃分「包含者/內容」和「集合/成員」兩種關係。其原因是﹕集合與成員之間亦可互為獨立﹐不具「生死與共」之親蜜關係﹔例如﹐「香港觀光行程」是獨立存在的﹐它既可含於東北亞總行程中﹐又可含於東南亞旅行團的總行程中。因之﹐「集合/成員」關係是一種特殊的「組合」(Composition) 結構。
  茲拿上節Person類別做為例子﹐如果Person之物件會加入Club(俱樂部)成為俱樂部的會員﹐則Club與Person之關係為「集合/成員」關係。茲定義Club類別如下﹕

'ex05.bas
Imports System.ComponentModel
Imports System.Drawing
Imports System.WinForms
Imports System.Collections
'----------------------------------------------------
Class Person
  Private p_name As String
  Private p_age As Integer
 
  Public Sub New(ByVal na As String, ByVal a As Integer)
  p_name = na
  p_age = a
  End Sub
  Public Sub display()
  Messagebox.Show(Me.p_name + ", " + str(Me.p_age))
  End Sub
End Class

Class Club
  Private c_name As String
  Private pa As ArrayList
 
  Public Sub New(ByVal na As String)
  c_name = na
  pa = New ArrayList()
  End Sub
  Public Sub join(ByVal p As Person)
  pa.Add(p)
  End Sub
  Public Sub display()
  Messagebox.Show("Club: " + Me.c_name + "  has member:")
  Dim p As Person
  For Each p In pa
  p.display()
  Next
  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 x As New Club("sogo")
  Dim a As New Person("Alvin", 32)
  Dim b As New Person("Judy", 28)
  x.join(a)
  x.join(b)
  x.display()
  End Sub
End Class


此程式輸出﹕
Club: sogo has member:
Alvin, 32
Judy, 28

c_name 指向Strclass之物件﹐這物件內含俱樂部之名稱。pa指向ArrayList之物件﹐這物件可包含許多會員(Person)物件。join()程式將Person之物件存入pa所指的ArrayList物件中。
  Club之物件含ArrayList之物件﹐此集合物件(Collections)含有Person之物件﹐表達了「集合/成員」關係。例如﹐x 物件內含a 和b 物件。

 

  此圖表示﹕"sogo"俱樂部共有"Alvin" 和"Judy"兩個會員﹐亦即x 是「集合」﹐而a 和b 是「成員」(Member)。
  值得注意﹕這軟體是利用已有類別──Strclass及Integer組合成應用類別──Person。再利用Person類別及ArrayList 類別組合成更復雜之應用類別──Club。未來﹐可利用Club及其它類別構築更大的應用類別﹐依此類推﹐便能創造龐大又可靠的軟體了。例如:

'ex06.bas
Imports System.ComponentModel
Imports System.Drawing
Imports System.WinForms
Imports System.Collections
'----------------------------------------------------
Class Person
  Private p_name As String
  Private p_age As Integer
  Public Sub New(ByVal na As String, ByVal a As Integer)
  p_name = na
  p_age = a
  End Sub
  Public Sub display()
  Messagebox.Show(Me.p_name + ", " + str(Me.p_age))
  End Sub
End Class

Class Club
  Private c_name As String
  Private pa As ArrayList
 
  Public Sub New(ByVal na As String)
  c_name = na
  pa = New ArrayList()
  End Sub
  Public Sub join(ByVal p As Person)
  pa.Add(p)
  End Sub
  Public Sub display()
  Messagebox.Show("Club: " + Me.c_name + "  has member:")
  Dim p As Person
  For Each p In pa
  p.display()
  Next
  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 x(2) As Club
  x(0) = New Club("sogo")
  x(1) = New Club("gold")
  Dim a As New Person("Alvin", 32)
  Dim b As New Person("Judy", 28)
  Dim c As New Person("Bob", 38)
  x(0).join(a)
  x(0).join(b)
  x(1).join(b)
  x(1).join(c)
  x(0).display()
  x(1).display()
  End Sub
End Class

此程式輸出:

Club: sogo has member:
  Alvin, 32
  Judy, 28
Club: gold has member:
  Judy, 28
  Bob, 38

  組合物件x 含"sogo"及"gold"兩俱樂部﹐其中"gold"俱樂部擁有兩個會員──"Alvin" 及"Judy"﹐而"sogo"俱樂部擁有兩位會員──"Judy"及"Bob" 。x(0)代表"sogo"俱樂部﹐s(1)代表"gold"俱樂部﹐所以指令── s(0).join( a ) 表示a 加入"gold"俱樂部﹐成為其會員。n


 


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/10752043/viewspace-987812/,如需轉載,請註明出處,否則將追究法律責任。

相關文章