設計模式之工廠方法(FACTORY METHOD))(一)
2024-07-21 02:23:37
供稿:網友
工廠方法
the factory method
我們已經學會了簡單工廠模式(simple factory pattern),工廠(factory)思想貫穿于整個面向對象編程(oop)以及其他一些設計模式的始終。如:生成器(builder)模式。其間,一個單一的類扮演類似交通警察的角色,決定哪一個單一層次上的子類將被實例化。
工廠方法模式(factory method pattern)是對工廠(factory)思想進行了巧妙的延伸,它使得將超類的實例化延遲到它的每一個子類。這個模式沒有具體的指出延遲到哪一個子類,而是定義一個抽象類創建對象,讓其子類決定創建哪一個對象。
下面是一個簡單的例子,在一個游泳比賽中如何確定游泳運動員的泳道。按照運動員的成績排列決賽事的分組,速度越快所分的小組的決賽的次序越靠后,反之,速度越慢就越先比賽,而且在每一個小組中成績越好、速度越快的選手也就越靠近中間的泳道。這被稱為straight seeding。
當游泳運動員在錦標賽比賽過程中,他們通常要游兩次。 通過在預賽中相互競爭,前12名或者16名游泳運動員將繼續在決賽中繼續彼此競爭。 為了預賽工作更公平, 采用circle seeded,這樣使得速度最快的3名選手分別處于最迅速3個小組的中心泳道。在剩下的選手中再選出速度最好的3名選手,等等。
我們要實現這個選拔模式并且使用工廠方法。
首先,設計抽象事件類:
public class events
protected numlanes as integer
protected swmmers as swimmers
'-----
public sub new(byval filename as string, byval lanes as integer)
mybase.new()
dim s as string
dim sw as swimmer
dim fl as vbfile
fl = new vbfile(filename) '打開一個文本文件
fl.openforread()
numlanes = lanes '保存泳道數量信息
swmmers = new swimmers
'讀取游泳選手信息
s = fl.readline
while not fl.feof
sw = new swimmer(s) '建立對象
swmmers.add(sw) 'add to list
s = fl.readline
end while
fl.closefile()
end sub
'-----
public function getswimmers() as arraylist
getswimmers = swmmers
end function
'-----
public overridable function isprelim() as boolean
end function
'-----
public overridable function isfinal() as boolean
end function
'-----
public overridable function istimedfinal() as boolean
end function
'-----
public overridable function getseeding() as seeding
end function
end class
因為所有的派生類都要從文本文件讀取數據,所以,我們把events類作為基類。其中所定義的方法均為虛方法,可以通過繼承events類來實現具體的類(prelimevent類、timedfinalevent類),這兩個類之間唯一的不同就是返回的選拔的類別不同。我們也定義了一個包含以下方法的抽象選拔類:
public mustinherit class seeding
protected numlanes as integer
protected laneorder as arraylist
protected numheats as integer
private asw() as swimmer
protected sw as swimmers
'-----
public function getseeding() as swimmers
getseeding = sw
end function
'-----
public function getheat() as integer
end function
'-----
public function getcount() as integer
getcount = sw.count
end function
'-----
public mustoverride sub seed()
'-----
public function getswimmers() as arraylist
getswimmers = sw
end function
'-----
public function getheats() as integer
return numheats
end function
'-----
public function odd(byval n as integer) as boolean
odd = (n / 2) * 2 <> n
end function
'-----
public function calclaneorder(byval lns as integer) as arraylist
numlanes = lns
dim lanes(numlanes) as integer
dim i as integer
dim mid, incr, ln as integer
mid = (numlanes / 2)
if (odd(numlanes)) then
mid = mid + 1
end if
incr = 1
ln = mid
for i = 0 to numlanes - 1
lanes(i) = ln
ln = mid + incr
incr = -incr
if (incr > 0) then
incr = incr + 1
end if
next i
laneorder = new arraylist
for i = 0 to numlanes - 1
laneorder.add(lanes(i))
next i
calclaneorder = laneorder
end function
public sub new(byval swmrs as swimmers, byval lanes as integer)
mybase.new()
sw = swmrs
numlanes = lanes
end sub
'-------------------
public function sort(byval sw as swimmers) as swimmers
dim i, j, max as integer
dim tmp as swimmer
try
max = sw.count
dim asw(max) as swimmer
for i = 0 to max - 1
asw(i) = ctype(sw.item(i), swimmer)
next i
for i = 0 to max - 1
for j = i to max - 1
if asw(i).gettime > asw(j).gettime then
tmp = asw(i)
asw(j) = asw(i)
asw(i) = tmp
end if
next j
next i
sw = new swimmers
for i = 0 to max - 1
sw.add(asw(i))
next i
sort = sw
catch e as exception
console.writeline("caught " + i.tostring + " " + j.tostring + " " + max.tostring + " " + e.tostring())
console.writeline(e.stacktrace)
end try
end function
end class