国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 編程 > .NET > 正文

VB.Net中文教程(2) Composite樣式

2024-07-10 13:01:18
字體:
來源:轉載
供稿:網友
1. 從whole-part關系談起
回想傳統的軟件師﹐常甚專注于撰寫程序(procedure) 來處理某些資料(data)﹐較少關心軟件的整體結構(architecture)。在現在的oo軟件中﹐把資料及其相關的程序結合在一起﹐封裝(encapsulate) 在對象之中。軟件師在使用對象時﹐通常把對象視為黑箱(black-box) ﹐不會關心于對象內部之細節﹔因之能專注于對象之間的關系。軟件師的主要工作﹐就是在于建立對象之間的互助合作(collaboration) 關系﹐為對象安排應盡之角色(role)﹐至于對象內部之細節﹐反而不頂重要。如此﹐可讓軟件師著重于軟件的整體架構上﹐而不會一頭栽進程序的執行細節之中。這避免了見樹不見林的缺點﹐放寬了軟件師的眼界﹐為軟件的多用途(reusability) 及彈性(flexibility) 著想﹐可創造長壽的軟件﹗
對象之間的常見關系有許多種﹐其中之一就是whole-part關系。像一朵花是由花蕊、花瓣、襯葉等所構成的﹐這朵花是個「整體」(whole)﹐而花蕊、花瓣等則是這整體的「一部分」(part)。再如﹐下圖的windows畫面上﹐form1 對象包含著3 個控制對象(control) ﹐這些控制對象成為form1 的一部分。因之﹐form1 是個整體﹐而各控制對象則是form1 對象的一部分。


圖1 、form1 對象包含3 個控制對象

我們可使用uml圖形表示為﹕

圖2、whole-part關系與繼承關系

這圖包括了whole-part關系﹐以及繼承關系。
● 菱形 符號表示whole-part關系﹔就是form1 對象可包含有數個control 對象。
● 箭頭 符號表示繼承關系﹔就是control 對象可細分為數個種類。

本文專注于whole-part關系﹐為composite樣式建立基礎。whole-part關系可分為兩種﹕
◎「部分」對象之個數是確定的。例如﹐1 輛汽車含有1 個方向盤﹐1 個form對象含有1 個抬頭(caption) 對象﹐1 只青蛙有4 條腿等等。在這種確定情形﹐可視為下述「可變」情形的特例。
◎「部分」對象之個數是可變的。例如﹐1 個form對象內含多個控制對象﹐1 棵樹含有成千上萬葉子﹐1 位學生的成績單上列有各科目的成績等等。這種whole-part關系通常得藉集合(collection)對象來表達之﹐如vb 的arraylist對象就可派上用場了。


2. 簡單的whole-part關系

最單純的whole-part關系就是某對象「內含」(contain) 其它對象。例如﹐
s 1 張訂單上面列示著多個采購的產品項目
s 1 支棒球隊擁有數字教練及多位球員
s 學生的成績單上印有多項成績
s 1 篇文章是由許多句子所組成
s 屏幕上的選擇表(menu)內含數個選擇項
s 1 份考卷包含數十道考題
......

就拿訂單(order form)的例子來說﹐訂單上常列有多個采購項目(order line)。


圖3、 訂單的例子

每個采購項目通常包括有產品名稱、采購數量、金額等。為了簡單起見﹐假設采購項目只含產品名稱及金額兩個項目﹐可藉uml圖表示「訂單」與「采購項目」之間的whole-part關系﹐如下圖所示﹕


圖4、以uml表達簡單的whole-part關系

在以vb落實這個uml模式時,則可藉vb的arraylist集合對象來實作(implement)「訂單」與「采購項目」之間的whole-part關系﹐如下圖所示﹕


圖5、以uml表達簡單的whole-part關系

現在的vb軟件師需要很習慣于掌握這種whole-part關系﹐且常藉集合對象來表示之。請看實際的vb程序﹐其中定義order 及orderline 兩個類別﹕

'ex01.bas
imports system.componentmodel
imports system.drawing
imports system.winforms
imports system.collections
'----------------------------------------------------
class orderline
private pname as string
private amt as double
public sub new(byval na as string, byval am as double)
pname = na
amt = am
end sub
public function name() as string
name = pname
end function
public function amount() as double
amount = amt
end function
end class

class order
private orderid as string
private lines as arraylist
public sub new(byval id as string)
orderid = id
lines = new arraylist()
end sub
public sub addline(byval ln as orderline)
lines.add(ln)
end sub
public function amount() as double
dim total as double = 0
dim ln as orderline
for each ln in lines
total = total + ln.amount()
next
amount = total
end function
public function getorderid() as string
getorderid = orderid
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 ord as new order("order777")
dim pline as orderline
pline = new orderline("pencil", 88.25)
ord.addline(pline)

pline = new orderline("ballpen", 110.5)
ord.addline(pline)
messagebox.show(ord.getorderid + "'s amount = " + str(ord.amount()))
end sub
end class

此程序輸出:
order777's cost = 198.75

在order 類別中定義了lines變量﹐其型態arraylist﹐表示lines將可代表1 個arraylist之對象﹐其本質上就是lines變量,內含一個參考值﹐參考到arraylist之對象。在order類別的建構程序 ---- new()里,誕生了arraylist對象﹐并將參考值存入lines里。各程序之定義如下﹕
order 類別的amount()程序計算出該訂單的總金額。addline() 則在訂單上新增一個采購項目。在form1_click()中﹐ord 對象內含一個lines集合對象﹐它容納2 個orderline對象。如此就表達了訂單與采購項目之間的whole-part關系了。
上述程序相當于 -----

'ex02.bas
imports system.componentmodel
imports system.drawing
imports system.winforms
imports system.collections
'----------------------------------------------------
class order
class orderline
public pname as string
public amt as double
end class

private orderid as string
private lines as arraylist

public sub new(byval id as string)
orderid = id
lines = new arraylist()
end sub
public sub addline(byval pna as string, byval am as double)
dim ln as orderline
ln = new orderline()
ln.pname = pna
ln.amt = am
lines.add(ln)
end sub
public function amount() as double
dim total as double = 0
dim ln as orderline
for each ln in lines
total = total + ln.amt
next
amount = total
end function
public function getorderid() as string
getorderid = orderid
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 ord as new order("order777")
ord.addline("pencil", 88.25)
ord.addline("ballpen", 110.5)
messagebox.show(ord.getorderid + "'s amount = " + str(ord.amount()))
end sub
end class

此程序輸出:
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

aly1 = new assemblypart("bulb")
p1 = new piecepart("body", 88.25)
aly1.add(p1)
p1 = new piecepart("head", 100.5)
aly1.add(p1)

aly2 = new assemblypart("light")
aly2.add(aly1)
p1 = new piecepart("cover", 10)
aly2.add(p1)
messagebox.show(aly2.name() + "'s cost = " + str(aly2.cost()))

p1 = aly2.getchild(0)
messagebox.show(p1.name + "'s cost = " + str(p1.cost()))

p2 = aly2.getchild(1)
messagebox.show(p2.name + "'s cost = " + str(p2.cost()))

p2 = p1.getchild(0)
messagebox.show(p2.name + "'s cost = " + str(p2.cost()))
end sub
end class

此程序輸出: light's cost = 198.75
bulb's cost = 188.75
cover's cost = 10
body's cost = 88.25

piecepart 代表最下層的基本對象。而assemblypart則代表中層的半成品對象組件﹐或代表成品。part為一個抽象類別,定義piecepart與assemblypart類別的共同部份(包括屬性和行為),供piecepart與assemblypart子類別來繼承之。此外,提供一個接口ipart給client使用,以封裝part、piecepart和assemblypart類別,創造part、piecepart和assemblypart類別的彈性調整空間,這是非常重要的。
form1_click()程序建立了有關「汽車車燈」的對象結構表﹕


圖8、vb程序所誕生的對象關系圖

p1 = aly2.getchild(0)取出「燈泡」小對象﹐并由p1代表這個小對象。p2 = p1.getchild(0) 取出「燈帽」小對象﹐并由p2代表之。依上述之樣式﹐可表達出無限層次的遞歸式whole-part關系。
為了讓軟件能永續生存下去﹐必須特別重視軟件的組織與其整體架構(architecture)。于是﹐設計軟件時,必須專注于對象之間的互助合作關系。一旦建立了理想的關系﹐就可以讓對象之間互相傳遞訊息、互相溝通了。例如﹐form1 對象傳送cost訊息給aly2對象﹐aly2對象就依循arraylist對象所建立的關系來將cost訊息遞給內含之各小對象。當各小對象回報其成本金額﹐aly2將之累計再傳送回到form1 對象﹐然后顯示在窗口畫面上。此刻﹐相信您已經進一步了解whole-part關系﹐善用arraylist集合類別來表達之,并更會運用vb來落實樣式,創造出更美好的軟件。■

[注1] erich gamma,design patterns: elements of reusable object-oriented software, addition-wesley, 1995.

菜鳥學堂:
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 昭平县| 辽宁省| 广德县| 石棉县| 乌兰察布市| 双鸭山市| 兰溪市| 延吉市| 赣榆县| 城固县| 新竹市| 石首市| 舟山市| 泽普县| 肃宁县| 伊宁县| 疏勒县| 英超| 扶风县| 华容县| 广宁县| 额敏县| 衡南县| 鄂托克前旗| 晋州市| 桃江县| 五台县| 商河县| 如皋市| 视频| 两当县| 子长县| 台前县| 崇明县| 临沧市| 乐安县| 西平县| 松滋市| 台湾省| 西青区| 南郑县|