VB.Net中文教程(13) Whole-Part关系
2024-07-10 13:02:42
供稿:网友
主题: whole-part关系
?????????? 内容 ??????????
v 1. 对象whole-part关系
v 2. 组合/部分关系
v 3. 包含者/内容关系
v 4. 集合/成员关系
1. 对象whole-part关系
类别继承(class inheritance)和对象组合(object 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.winforms
'---------------------------------------------------------------------------------
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 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 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
0
1
「组合」对象之建构者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 driver
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