小男孩‘自慰网亚洲一区二区,亚洲一级在线播放毛片,亚洲中文字幕av每天更新,黄aⅴ永久免费无码,91成人午夜在线精品,色网站免费在线观看,亚洲欧洲wwwww在线观看

分享

Simple Facotry from:UML軟件工程組織-火龍果軟件

 deepblue 2007-05-03
Simple Facotry
 
作者:Hacken的專欄  來源:網(wǎng)絡(luò)
 

創(chuàng)建型模式

 創(chuàng)建型模式(Creational Pattern)對(duì)類的實(shí)例化過程進(jìn)行了抽象,能夠使軟件模塊做到與對(duì)象創(chuàng)建和組織的無關(guān)性。為了使體系結(jié)構(gòu)更加清晰,一些軟件在設(shè)計(jì)上要求當(dāng)創(chuàng)建類的具體實(shí)例時(shí),能夠根據(jù)具體的語境來動(dòng)態(tài)地決定怎樣創(chuàng)建對(duì)象,創(chuàng)建哪些對(duì)象,以及怎樣組織和表示這些對(duì)象,而創(chuàng)建型模式所要描述的就是該如何來解決這些問題。

按照生成目標(biāo)的不同,創(chuàng)建型模式可以分為類的創(chuàng)建型模式和對(duì)象的創(chuàng)建型模式兩種:

  • 類的創(chuàng)建型模式
    類的創(chuàng)建型模式通過使用繼承關(guān)系,將類的創(chuàng)建交由具體的子類來完成,這樣就向外界隱藏了如何得到具體類的實(shí)現(xiàn)細(xì)節(jié),以及這些類的實(shí)例是如何被創(chuàng)建和組織在一起的。
  • 對(duì)象的創(chuàng)建型模式
    對(duì)象的創(chuàng)建型模式通過把對(duì)象的創(chuàng)建委托給另一個(gè)對(duì)象來完成,可以根據(jù)語境動(dòng)態(tài)地決定生成哪些具體類的實(shí)例,同時(shí)還可以向外界隱藏這些實(shí)例是如何被創(chuàng)建以及如何被組織在一起的細(xì)節(jié)。

所有的創(chuàng)建型模式都有兩個(gè)永恒的主旋律:第一,它們都將系統(tǒng)使用哪些具體類的信息封裝起來;第二,它們隱藏了這些類的實(shí)例是如何被創(chuàng)建和組織的。外界對(duì)于這些對(duì)象只知道它們共同的接口,而不清楚其具體的實(shí)現(xiàn)細(xì)節(jié)。正因如此,創(chuàng)建型模式在創(chuàng)建什么(what),由誰(who)來創(chuàng)建,以及何時(shí)(when)創(chuàng)建這些方面,都為軟件設(shè)計(jì)者提供了盡可能大的靈活性。

具體到Python來說,假設(shè)有這樣一個(gè)類:

class Person: def __init__(self, name): self.name = name

要?jiǎng)?chuàng)建該類的一個(gè)實(shí)例,則應(yīng)該執(zhí)行下面的語句:

p = Person("Gary")

但如果創(chuàng)建對(duì)象時(shí)完成的工作非常復(fù)雜,需要一段很長(zhǎng)的代碼,你就不能簡(jiǎn)單地將其全部寫入__init__方法中,因?yàn)檫@會(huì)違背面向?qū)ο笏枷氲膬蓚€(gè)基本原則:封裝(encapsulation)和委派(delegation)。假如執(zhí)意要做樣做,結(jié)果只會(huì)使你的代碼變成一段行為固定的硬編碼(hard coding),而整個(gè)軟件的結(jié)構(gòu)都極有可能變得非常糟糕,因?yàn)槠渌硞€(gè)模塊也許就正依賴于你所創(chuàng)建的這個(gè)實(shí)例,這樣就在無形之間增加了模塊之間的耦合度。

將Python對(duì)象的創(chuàng)建過程封裝到某個(gè)類中來單獨(dú)完成,可以使你的程序變得更加靈活和通用。實(shí)踐證明,使用下面的六種創(chuàng)建型模式可以更好地改善對(duì)象的創(chuàng)建過程:

  • Simple Factory模式
      專門定義一個(gè)類來負(fù)責(zé)創(chuàng)建其它類的實(shí)例,被創(chuàng)建的實(shí)例通常都具有共同的父類。
  • Factory Method模式
      將對(duì)象的創(chuàng)建交由父類中定義的一個(gè)標(biāo)準(zhǔn)方法來完成,而不是其構(gòu)造函數(shù),究竟應(yīng)該創(chuàng)建何種對(duì)象由具體的子類負(fù)責(zé)決定。
  • Abstract Factory模式
      提供一個(gè)共同的接口來創(chuàng)建相互關(guān)聯(lián)的多個(gè)對(duì)象。
  • Singleton模式
      保證系統(tǒng)只會(huì)產(chǎn)生該類的一個(gè)實(shí)例,同時(shí)還負(fù)責(zé)向外界提供訪問該實(shí)例的標(biāo)準(zhǔn)方法。
  • Builder模式
      將復(fù)雜對(duì)象的創(chuàng)建同它們的具體表現(xiàn)形式(representation)區(qū)別開來,這樣可以根據(jù)需要得到具有不同表現(xiàn)形式的對(duì)象。
  • Prototype模式
      利用一個(gè)能對(duì)自身進(jìn)行復(fù)制的類,使得對(duì)象的動(dòng)態(tài)創(chuàng)建變得更加容易。

二、模式引入

簡(jiǎn)單工廠(Simple Factory)模式又稱為靜態(tài)工廠方法(Static Factory Method)模式,屬于類的創(chuàng)建型模式。這種模式根據(jù)外界給定的信息,由"工廠"對(duì)象"制造"出某些可能"產(chǎn)品"類中的一個(gè)實(shí)例,工廠對(duì)象能夠處理的所有類通常都繼承于同一個(gè)父類,并且對(duì)外界提供基本相同的接口,只不過在具體實(shí)現(xiàn)時(shí)會(huì)有所差別罷了。

假設(shè)我們要開發(fā)一個(gè)繪圖程序,用來繪制簡(jiǎn)單的幾何圖形,這個(gè)軟件應(yīng)該能夠處理下面的幾種幾何對(duì)象:

  • 圓形(Circle)
  • 矩形(Rectangle)
  • 菱形(Diamond)

除了各自特有的屬性和方法之外,所有的幾何圖形幾乎都可以抽象出繪制(draw)和擦除(erase)兩個(gè)公共方法,因而可以為它們定義一個(gè)共同的接口Shape。雖然Python語言本身并不支持接口,但為了更好地闡明設(shè)計(jì)模式的思想,有時(shí)我們還是會(huì)借用一下UML中的接口這一概念。這樣一來,各個(gè)類之間的關(guān)系就將如圖1所示:


 圖1

Shape接口定義了所有幾何圖形都必須實(shí)現(xiàn)的公共方法: draw()和erase(),實(shí)現(xiàn)該接口的Python代碼如下所示,Python中沒有接口的概念,因此在具體實(shí)現(xiàn)時(shí)可以使用類來替代。

代碼清單1:shape.pyclass Shape: # 繪制圖形 def draw(self): pass # 擦除圖形 def erase(self): pass

Circle類是Shape的一種具體形式,它實(shí)現(xiàn)了Shape接口定義的所有方法,此外還添加了一個(gè)屬性__radius,用來表示圓的半徑。以下是實(shí)現(xiàn)Circle類的代碼:

代碼清單2:circle.pyclass Circle (Shape): def __init__(self, radius = 0): self.__radius = radius # 繪制圓形 def draw(self): print "Draw Circle" # 擦除圓形 def erase(self): print "Erase Circle" # 半徑的取值方法 def getRadius(self): return self.__radius # 半徑的賦值方法 def setRadius(self, radius): self.__radius = radius

Rectangle類也是Shape的一種具體形式,它實(shí)現(xiàn)了Shape接口定義的所有方法,并添加了__width和__height兩個(gè)屬性,分別表示矩形的寬度和高度。以下是實(shí)現(xiàn)Rectangle類的代碼:

代碼清單3:rectangle.pyclass Rectangle (Shape): def __init__(self, width = 0, height = 0): self.__width = width self.__height = height # 繪制矩形 def draw(self): print "Draw Rectangle" # 擦除矩形 def erase(self): print "Erase Rectangle" # 寬度的取值方法 def getWidth(self): return self.__width # 寬度的賦值方法 def setWidth(self, width): self.__width = width # 高度的取值方法 def getHeight(self): return self.__height # 高度的賦值方法 def setHeight(self, height): self.__height = height

同樣,Diamond類也是Shape的一種具體形式,它實(shí)現(xiàn)了Shape接口中定義的所有方法,并且添加了__width和__height兩個(gè)屬性,分別表示菱形的寬度和高度。以下是實(shí)現(xiàn)Diamond類的代碼:

代碼清單4:diamond.pyclass Diamond (Shape): def __init__(self, width = 0, height = 0): self.__width = width self.__height = height # 繪制菱形 def draw(self): print "Draw Diamond" # 擦除菱形 def erase(self): print "Erase Diamond" # 寬度的取值方法 def getWidth(self): return self.__width # 寬度的賦值方法 def setWidth(self, width): self.__width = width # 高度的取值方法 def getHeight(self): return self.__height # 高度的賦值方法 def setHeight(self, height): self.__height = height

所有幾何圖形類都定義好后,下面要做的就是提供一個(gè)"工廠"類ShapeFactory,來創(chuàng)建各種幾何圖形的具體實(shí)例。ShapeFactory類的作用就是根據(jù)外界的要求,創(chuàng)建出不同的幾何圖形對(duì)象,如圓形(Circle)、矩形(Rectangle)或菱形(Diamond),這樣整個(gè)軟件的體系結(jié)構(gòu)就將如圖2所示。


 圖2

ShapeFactory類用于創(chuàng)建各種幾何圖形的實(shí)例,其實(shí)現(xiàn)代碼如下所示:

代碼清單5:shapefactory.pyclass ShapeFactory: def factory(self, which): if which == "Circle": return Circle() elif which == "Rectangle": return Rectangle() elif which == "Diamond": return Diamond() else: return None

在ShapeFactory類中只定義了一個(gè)方法factory(),外界通過調(diào)用該方法,來創(chuàng)建其所需的幾何圖形對(duì)象,但如果所請(qǐng)求的類是系統(tǒng)所不支持的,則將返回None。在引入了工廠類之后,其它模塊如果想生成幾何圖形類的實(shí)例,只需調(diào)用ShapeFactory類的factory()方法就可以了:

fac = ShapeFactory()shape = fac.factory("Diamond")if shape != None: shape.draw()

就樣就成功地將類是如何創(chuàng)建的這一實(shí)現(xiàn)細(xì)節(jié)向外界隱藏起來了,這就是簡(jiǎn)單工廠模式所采取的基本策略。

三、一般結(jié)構(gòu)

簡(jiǎn)單工廠模式屬于類的創(chuàng)建型模式,適合用來對(duì)大量具有共同接口的類進(jìn)行實(shí)例化,它可以推遲到運(yùn)行的時(shí)候才動(dòng)態(tài)決定要?jiǎng)?chuàng)建哪個(gè)類的實(shí)例,而不是在編譯時(shí)就必須知道要實(shí)例化哪個(gè)類。簡(jiǎn)單工廠模式的一般性結(jié)構(gòu)如圖3所示:


 圖3

簡(jiǎn)單工廠模式的實(shí)質(zhì)是由一個(gè)工廠類根據(jù)傳入的參量,動(dòng)態(tài)決定應(yīng)該創(chuàng)建出哪一個(gè)產(chǎn)品類的實(shí)例。從上圖可以看出,簡(jiǎn)單工廠模式涉及到工廠角色、抽象產(chǎn)品角色和具體產(chǎn)品角色三個(gè)參與者。

  • 工廠(Creator)角色
    是簡(jiǎn)單工廠模式的核心,它負(fù)責(zé)實(shí)現(xiàn)創(chuàng)建所有實(shí)例的內(nèi)部邏輯。工廠類可以被外界直接調(diào)用,創(chuàng)建所需的產(chǎn)品對(duì)象。
  • 抽象產(chǎn)品(Product)角色
    是簡(jiǎn)單工廠模式所創(chuàng)建的所有對(duì)象的父類,它負(fù)責(zé)描述所有實(shí)例所共有的公共接口。
  • 具體產(chǎn)品(Concrete Product)角色
    是簡(jiǎn)單工廠模式的創(chuàng)建目標(biāo),所有創(chuàng)建的對(duì)象都是充當(dāng)這個(gè)角色的某個(gè)具體類的實(shí)例。

工廠角色負(fù)責(zé)創(chuàng)建一個(gè)具體產(chǎn)品的實(shí)例,并將其返回給調(diào)用者,以下是工廠類的示例性Python代碼:

代碼清單6:creator.pyclass Creator: # 創(chuàng)建具體產(chǎn)品類的方法 def factory(self): return ConcreteProduct()

抽象產(chǎn)品角色的主要目的是為所有的具體產(chǎn)品提供一個(gè)共同的接口,通常只需給出相應(yīng)的聲明就可以了,而不用給出具體的實(shí)現(xiàn)。以下是抽象產(chǎn)品類的示例性Python代碼:

代碼清單7:product.pyclass Product: # 所有具體產(chǎn)品類的公共接口 def interface(self): pass

具體產(chǎn)品角色充當(dāng)最終的創(chuàng)建目標(biāo),一般來講它是抽象產(chǎn)品類的子類,實(shí)現(xiàn)了抽象產(chǎn)品類中定義的所有接口方法。以下是具體產(chǎn)品類的示例性Python代碼:

代碼清單8:concrete.pyclass ConcreteProduct(Product): # 公共接口的實(shí)現(xiàn) def interface(self): print "Concrete Product Method"

在應(yīng)用簡(jiǎn)單工廠模式時(shí),可以采用下面的示例性Python代碼:

fac = Creator()p = fac.factory()if p != None: p.interface()

在這個(gè)簡(jiǎn)單的示意性實(shí)現(xiàn)里,充當(dāng)具體產(chǎn)品角色的類只有一個(gè),但在真正的實(shí)際應(yīng)用中,通常遇到的都是同時(shí)有多個(gè)具體產(chǎn)品類的情況。

四、實(shí)際運(yùn)用

在運(yùn)用簡(jiǎn)單工廠模式開發(fā)真正的軟件系統(tǒng)時(shí),抽象產(chǎn)品和具體產(chǎn)品之間可能會(huì)形成非常復(fù)雜的樹狀結(jié)構(gòu),如圖4所示。
 
 圖4

雖然這樣的結(jié)構(gòu)并不符合所有具體產(chǎn)品類都繼承于同一抽象產(chǎn)品類的基本原則,但也不難發(fā)現(xiàn)其實(shí)所有的具體產(chǎn)品類歸根結(jié)底都源自于同一個(gè)抽象產(chǎn)口類,遇到這種情況時(shí)只需稍加變通,依然能夠使用同一個(gè)工廠類來創(chuàng)建所有具體產(chǎn)品類的實(shí)例,只不過此時(shí)的軟件結(jié)構(gòu)將如圖5所示。


 圖5

當(dāng)抽象產(chǎn)品類和具體產(chǎn)品類的關(guān)系變得復(fù)雜起來時(shí),使用簡(jiǎn)單工廠模式的一個(gè)好處就是各種產(chǎn)品類之間的結(jié)構(gòu)關(guān)系不會(huì)反映到工廠類中,并且它們結(jié)構(gòu)上的變化也不會(huì)影響到工廠類。正是因?yàn)楹?jiǎn)單工廠模式對(duì)各種具體產(chǎn)品類者是單獨(dú)對(duì)待的,因此工廠類并不需要弄清楚它們之間的結(jié)構(gòu)關(guān)系,而只需知道究竟有哪些具體產(chǎn)品類可以被實(shí)例化以及如何實(shí)例化就可以了。不過這樣做有時(shí)也會(huì)產(chǎn)生一些麻煩,那就是在增加新的具體產(chǎn)品類時(shí),不可避免地會(huì)導(dǎo)致對(duì)工廠類的修改。

如果在實(shí)際中運(yùn)用簡(jiǎn)單工廠模式時(shí)遇到只有一個(gè)具體產(chǎn)品類的情況,為了簡(jiǎn)化軟件體系結(jié)構(gòu),可以考慮對(duì)簡(jiǎn)單工廠模式進(jìn)行精簡(jiǎn),省略抽象產(chǎn)品這一角色。此時(shí)簡(jiǎn)單工廠模式的結(jié)構(gòu)將如圖6所示。


 圖6

在簡(jiǎn)單廠模式中,充當(dāng)工廠角色的類通常只會(huì)有一個(gè)方法,那就是用來創(chuàng)建具體產(chǎn)品對(duì)象的factory()。在某些特殊場(chǎng)合下,如果需要的話也可以考慮將工廠角色的功能交由抽象產(chǎn)品角色來替代完成,這時(shí)簡(jiǎn)單工廠模式的結(jié)構(gòu)將如圖7所示。

圖7

在更極端的情況下,工廠角色、抽象產(chǎn)品角色和具體產(chǎn)品角色三者可以合并,即將所有的功能都交由具體產(chǎn)品類來統(tǒng)一完成。也就是說,簡(jiǎn)單工廠模式將退化成一個(gè)單獨(dú)的具體產(chǎn)品類,這個(gè)類同時(shí)也是自身的工廠,負(fù)責(zé)創(chuàng)建自己的實(shí)例,如圖8所示。


 圖8

這種退化的簡(jiǎn)單工廠模式從實(shí)質(zhì)上講等價(jià)于一個(gè)類,唯一不同的是在對(duì)象初始化時(shí)不再使用默認(rèn)的構(gòu)造方法,而是使用自定義的工廠方法,但這在許多場(chǎng)合下的意義并不是很大,尤其是對(duì)Python這種動(dòng)態(tài)類型語言來說更是如此。由于退化后的模式并沒有充分利用簡(jiǎn)單工廠模式的特點(diǎn),所以最好慎重使用,當(dāng)然也可以考慮用其它模式進(jìn)行替代。

五、優(yōu)勢(shì)和不足

在簡(jiǎn)單工廠模式中,工廠類是整個(gè)模式的關(guān)鍵所在,它包含必要的判斷邏輯,能夠根據(jù)外界給定的信息,決定究竟應(yīng)該創(chuàng)建哪個(gè)具體類的對(duì)象。通過使用工廠類,外界可以從直接創(chuàng)建具體產(chǎn)品對(duì)象的尷尬局面中擺脫出來,僅僅只需要負(fù)責(zé)"消費(fèi)"對(duì)象就可以了,而不必管這些對(duì)象究竟是如何創(chuàng)建以及如何組織的,這樣就清晰了各自的職責(zé)和權(quán)力,有利于整個(gè)軟件體系結(jié)構(gòu)的優(yōu)化。

不過,凡事有利就有弊,簡(jiǎn)單工廠模式的缺點(diǎn)也正體現(xiàn)在其工廠類上。由于工廠類集中了所有實(shí)例的創(chuàng)建邏輯,是一個(gè)無所不能的"全能類"(God Class),因此它對(duì)整個(gè)軟件系統(tǒng)是至關(guān)重要的,如果這個(gè)類無法正常工作,其它部分可能都會(huì)受到牽連,正所謂"城門失火,殃及池魚"。

將全部創(chuàng)建邏輯都集中到一個(gè)工廠類中還有另外一個(gè)缺點(diǎn),那就是當(dāng)系統(tǒng)中的具體產(chǎn)品類不斷增多時(shí),可能會(huì)出現(xiàn)要求工廠類根據(jù)不同條件創(chuàng)建不同實(shí)例的需求,這種對(duì)條件的判斷和對(duì)具體產(chǎn)品類型的判斷交織在一起,很難避免模塊功能的蔓延,對(duì)系統(tǒng)的擴(kuò)展和維護(hù)也非常不利。

簡(jiǎn)單工廠模式的這些缺點(diǎn),在下次將要介紹的工廠方法(Factory Method)模式中得到了一定程度上的克服,好了,下次再見吧!

六、小結(jié)

創(chuàng)建型模式的目標(biāo)是做到對(duì)象創(chuàng)建和組織的無關(guān)性,它可以細(xì)分為類的創(chuàng)建型模式和對(duì)象的創(chuàng)建型模式。簡(jiǎn)單工廠模式屬于類的創(chuàng)建型模式,它可以根據(jù)外界所給定的信息,用工廠對(duì)象制造出某種特定產(chǎn)品類的實(shí)例。完整的簡(jiǎn)單工廠模式包含工廠、抽象產(chǎn)品和具體產(chǎn)品三個(gè)角色,但在實(shí)際運(yùn)用時(shí)可以靈活掌握,對(duì)模型進(jìn)行簡(jiǎn)單化。簡(jiǎn)單工廠模式的優(yōu)點(diǎn)是它的工廠類能夠負(fù)責(zé)所有對(duì)象的創(chuàng)建,而缺點(diǎn)則是工廠類的實(shí)現(xiàn)邏輯可能過于復(fù)雜。

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類似文章 更多