目錄
python實踐設計模式(二)Builder,Singleton,Prototype
學習python有一段時間,之前就是看看書,最后發現只有實踐才能真正學到東西,只有在解決問題中才能真正掌握。之前大牛也有用python實現各種設計模式的,我自己參考之前在學習用C#實現設計模式的經歷,也想把23種模式逐一實踐,從網上查了一些資料,才明白python雖然是面向對象的,但是和C#,java語言不太一樣。影響設計方法不一樣有以下幾點:
1.python沒有接口Interface的類型。
2.由於《Design Patterns—Elements of Reusable Object-Oriented Software》一書采用的是C++來講述設計模式,因此訪問控制符(public、protected和private等關鍵字)和靜態成員方法(類方法)等都可以直接使用,但是這些特性在Python中都無法用到,原因是Python采了與C++完全不同的對象模式。
3.python不是強類型,弱化了多態的概念,一個對象很少只是一個類的實例,而是可以在運行時動態改變,支持相同請求的不同對象針對同一請求所觸發的操作可能完全不同。
4.python代碼生存在modules中而不必須在class中。
5.python有一些特殊語法運用了設計模式(如decorator ),可以直接應用。
有了以上的不同,就注定python在運用設計模式上與其他面向對象語言的不同,下面是我嘗試的實現。
《Design Patterns》一書把設計模式分為了3大類,創建型模式(creational pattern)、結構型模式(structural pattern)和行為型模式(behavioral patterns)。
一. 創建型模式(creational pattern)
對類的實例化過程進行了抽象,能夠使軟件模塊做到與對象創建和組織的無關性。為了使體系結構更加清晰,一些軟件在設計上要求當創建類的具體實例時,能夠根據具體的語境來動態地決定怎樣創建對象,創建哪些對象,以及怎樣組織和表示這些對象,而創建型模式所要描述的就是該如何來解決這些問題。
創建型模式包括以下幾種:
Simple Factory模式
專門定義一個類來負責創建其它類的實例,被創建的實例通常都具有共同的父類。
Factory Method模式
將對象的創建交由父類中定義的一個標准方法來完成,而不是其構造函數,究竟應該創建何種對象由具體的子類負責決定。
Abstract Factory模式
提供一個共同的接口來創建相互關聯的多個對象。
Singleton模式
保證系統只會產生該類的一個實例,同時還負責向外界提供訪問該實例的標准方法。
Builder模式
將復雜對象的創建同它們的具體表現形式(representation)區別開來,這樣可以根據需要得到具有不同表現形式的對象。
Prototype模式
利用一個能對自身進行復制的類,使得對象的動態創建變得更加容易。
本次先實踐Simple Factory模式,Factory Method模式和 Abstract Factory模式,其他模式后續會涉及。
1.Simple Factory模式
Simple Factory模式不是獨立的設計模式,他是Factory Method模式的一種簡單的、特殊的實現。他也被稱為靜態工廠模式,通常創建者的創建方法被設計為static方便調用,但是python沒有static一說。所以可以把創建者也就是工廠設計為一個普通class或全局函數即可。如果是class還需要實例化才能調用工廠方法,而全局函數比較簡單,比較接近靜態工廠的簡便特性。
Simple Factory模式包含以下角色部分,UML可參考下圖:
1) 工廠類角色:這是本模式的核心,含有一定的商業邏輯和判斷邏輯。由一個具體類實現,通常該類的工廠方法是靜態的。在python中工廠為一個普通class或全局函數。
2) 抽象產品角色:它一般是具體產品繼承的父類或者實現的接口。由接口或者抽象類來實現。在python中抽象產品一般為父類。
3) 具體產品角色:工廠類所創建的對象就是此角色的實例。由一個具體類實現。
一個Simple Factory模式代碼實例

1 class car: 2 '''interface as Product''' 3 def drive(self): 4 pass 5 6 class BMW(car): 7 '''Concrete Product''' 8 def __init__(self,carname): 9 self.__name=carname 10 def drive(self): 11 print "Drive the BMW as "+self.__name 12 13 class Benz(car): 14 '''Concrete Product''' 15 def __init__(self,carname): 16 self.__name=carname 17 def drive(self): 18 print "Drive the Benz as "+self.__name 19 20 class driver: 21 '''Factory also called Creator''' 22 def driverCar(self,name): 23 if name=="BMW": 24 return BMW("BMW") 25 elif name=="Benz": 26 return Benz("Benz") 27 else: 28 raise MyInputException(name) 29 30 class MyInputException(Exception): 31 def __init__(self, name): 32 Exception.__init__(self) 33 self.name = name 34 35 36 if __name__ == "__main__": 37 print "please input \"BMW\" or \"Benz\" :" 38 carname=raw_input() 39 dier=driver() 40 try: 41 d=dier.driverCar(carname) 42 except MyInputException,e: 43 print "input worry name "+e.name 44 else: 45 d.drive()
用全局函數改寫工廠類,其他部分省略,變化部分如下:
1 '''Factory also called Creator''' 2 def driver(name): 3 if name=="BMW": 4 return BMW("BMW") 5 elif name=="Benz": 6 return Benz("Benz") 7 else: 8 raise MyInputException(name) 9 10 if __name__ == "__main__": 11 print "please input \"BMW\" or \"Benz\" :" 12 carname=raw_input() 13 try: 14 d=driver(carname) 15 except MyInputException,e: 16 print "input worry name "+e.name 17 else: 18 d.drive()
2. Factory Method工廠模式
工廠方法模式去掉了簡單工廠模式中工廠方法的靜態屬性,使得它可以被子類繼承。對於python來說,就是工廠類被具體工廠繼承。這樣在簡單工廠模式里集中在工廠方法上的壓力可以由工廠方法模式里不同的工廠子類來分擔。也就是工廠外面再封裝一層。
1) 抽象工廠角色: 這是工廠方法模式的核心,它與應用程序無關。是具體工廠角色必須實現的接口或者必須繼承的父類。
2) 具體工廠角色:它含有和具體業務邏輯有關的代碼。由應用程序調用以創建對應的具體產品的對象。
3) 抽象產品角色:它是具體產品繼承的父類或者是實現的接口。在python中抽象產品一般為父類。
4) 具體產品角色:具體工廠角色所創建的對象就是此角色的實例。由一個具體類實現。
一個Factory Method代碼實例

1 class car: 2 '''interface as Product''' 3 def drive(self): 4 pass 5 6 class BMW(car): 7 '''Concrete Product''' 8 def __init__(self,carname): 9 self.__name=carname 10 def drive(self): 11 print "Drive the BMW as "+self.__name 12 13 class Benz(car): 14 '''Concrete Product''' 15 def __init__(self,carname): 16 self.__name=carname 17 def drive(self): 18 print "Drive the Benz as "+self.__name 19 20 class driver: 21 '''Factory also called Creator''' 22 def driverCar(self): 23 return car() 24 25 class BMWdriver(driver): 26 '''Concrete Creator''' 27 def driverCar(self): 28 return BMW("BMW") 29 30 class Benzdriver(driver): 31 '''Concrete Creator''' 32 def driverCar(self): 33 return Benz("Benz") 34 35 if __name__ == "__main__": 36 driver=BMWdriver() 37 car=driver.driverCar() 38 car.drive() 39 driver=Benzdriver() 40 car=driver.driverCar() 41 car.drive()
3. Abstract Factory模式
抽象工廠是工廠模式的進一步延伸,產品的類變的更加復雜,也就說產品不只是一個接口或父類而是有多個接口和父類了,形成了一個產品族的概念。模式的角色與Factory Method基本一樣,UML圖如下:
抽象工廠模式的用意為:給客戶端提供一個接口,可以創建多個產品族中的產品對象。 不過使用抽象工廠是有條件的:
1.系統中有多個產品族,而系統一次只可能消費其中一族產品
2.同屬於同一個產品族的產品在一起使用,這一約束必須在系統的設計中體現出來。
簡單的實現代碼如下:

1 class Newcar: 2 '''Abstract Product''' 3 def drive(self): 4 pass 5 6 class NewBMW(Newcar): 7 '''Concrete Product''' 8 def __init__(self,carname): 9 self.__name=carname 10 def drive(self): 11 print "Drive the New BMW as "+self.__name 12 13 class NewBenz(Newcar): 14 '''Concrete Product''' 15 def __init__(self,carname): 16 self.__name=carname 17 def drive(self): 18 print "Drive the New Benz as "+self.__name 19 20 class Oldcar: 21 '''Abstract Product''' 22 def drive(self): 23 pass 24 25 class OldBMW(Oldcar): 26 '''Concrete Product''' 27 def __init__(self,carname): 28 self.__name=carname 29 def drive(self): 30 print "Drive the Old BMW as "+self.__name 31 32 class OldBenz(Oldcar): 33 '''Concrete Product''' 34 def __init__(self,carname): 35 self.__name=carname 36 def drive(self): 37 print "Drive the Old Benz as "+self.__name 38 39 class driver: 40 '''Abstract Factory also called Creator''' 41 def driverNewCar(self): 42 return Newcar() 43 def driverOldCar(self): 44 return Oldcar() 45 46 class BMWdriver(driver): 47 '''Concrete Factory or Creator''' 48 def driverNewCar(self): 49 return NewBMW("NewBMW") 50 def driverOldCar(self): 51 return OldBMW("OldBMW") 52 53 class Benzdriver(driver): 54 '''Concrete Factory or Creator''' 55 def driverNewCar(self): 56 return NewBenz("NewBenz") 57 def driverOldCar(self): 58 return OldBenz("OldBenz") 59 60 if __name__ == "__main__": 61 driver=BMWdriver() 62 car=driver.driverNewCar() 63 car.drive() 64 car=driver.driverOldCar() 65 car.drive() 66 driver=Benzdriver() 67 car=driver.driverNewCar() 68 car.drive() 69 car=driver.driverOldCar() 70 car.drive()
未完待續……