此程序输出: Order777's cost = 198.75
3. 递归式Whole-part关系
Whole-part关系内含别的Whole-part关系﹐且允许有多层次的Whole-part关系﹐通称为递归式的Whole-part关系。在自然界中常见这种关系﹐例如﹐树叶是树的一部分﹐但树叶又是个整体﹐其内含着叶脉、叶绿素等「部分」对象。
图6、自然界的多层次Whole-part关系
在企业界﹐最典型的例子是「对象结构表」(bill of material简称BOM)﹐如下﹕
图7、企业物料表(BOM)的Whole-part关系
乍看之下,这些结构似乎很复杂﹐但从这些图形中﹐可看出这些对象可依其角色而分为两类﹕
1. Leaf对象。如上图里的「白色」类别之对象﹐它们不具有Whole 之角色﹐只具有part之角色。这通称为「基本组件」(primitive component) 。
2. Composite 对象。如上图中的「灰色」类别之对象﹐它们具有Whole之角色﹐也可能具有part之角色。这通称为「复合组件」(composite component) 。
因之﹐只需定义两个类别──Leaf及Composite 类别即行。
4. 以VB落实Composite样式
上述递归Whole-part关系是很常见的﹐是软件设计师惯用的手艺。因之﹐在Gamma 的"Design Patterns" 一书〔注1 〕中﹐也将之收录为重要的「样式」(Pattern) 之1。 该书所画的样式结构图如下图:
图8、Composite样式
这样式建议我们应定义Add() 、Remove()和GetChild()三个基本的可再定义的(overridable) 程序﹐以及其它的程序。专家们把这表示法视为样式﹐就意谓着﹕这是专家们所认为最理想的表达方式。现在﹐实际以依循这个样式来表达上述BOM 结构,必须定义下述类别: u Part类别 ----- 对应到Component u PiecePart类别 ----- 对应到Leaf u AssemblyPart类别 ----- 对应到Composite
再将之落实为VB程序,如下: 'ex03.bas Imports System.ComponentModel Imports System.Drawing Imports System.WinForms Imports System.Collections '---------------------------------------------------- Interface IPart Sub Add(ByVal p As IPart) Function GetChild(ByVal n As Integer) As IPart Function Cost() As Double Function Name() As String End Interface
Class Part Private pname As String Protected Sub New(ByVal na As String) pname = na End Sub Protected Function getName() As String getName = pname End Function End Class
Class PiecePart Implements IPart Inherits Part Private pcost As Double
Public Sub New(ByVal na As String, ByVal c As Double) MyBase.New(na) pcost = c End Sub Public Sub Add(ByVal p As IPart) Implements IPart.Add MessageBox.Show("Parts do not have Subparts") End Sub Public Function SubPart(ByVal n As Integer) As IPart Implements IPart.GetChild SubPart = Nothing End Function Public Function Cost() As Double Implements IPart.Cost Cost = pcost End Function Public Function Name() As String Implements IPart.Name Name = MyBase.getName() End Function End Class
Class AssemblyPart Implements IPart Inherits Part
Private children As ArrayList
Public Sub New(ByVal na As String) MyBase.New(na) children = New ArrayList() End Sub Public Sub Add(ByVal p As IPart) Implements IPart.Add children.Add(p) End Sub Public Function SubPart(ByVal n As Integer) As IPart Implements IPart.GetChild Dim obj As Object obj = children.Item(n) SubPart = CType(obj, IPart) End Function Public Function Cost() As Double Implements IPart.Cost Dim sum As Double Dim ps As IPart sum = 0 For Each ps In children sum = sum + ps.Cost() Next Cost = sum End Function Public Function Name() As String Implements IPart.Name Name = MyBase.getName() 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 aly1, aly2, p1, p2 As IPart Dim ps As IPart
(编辑:aniston)
|