2015年12月24日 星期四

[ Python 文章收集 ] python實踐設計模式(一)概述和工廠模式

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

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

簡單的實現代碼如下: 
- AbstractFactory_test.py 
  1. #!/usr/bin/env python  
  2. class Newcar:  
  3.     ''' Abstract Product '''  
  4.     def drive(self):  
  5.         pass  
  6.   
  7. class NewBMW(Newcar):  
  8.     ''' Concrete Product '''  
  9.     def __init__(self,carname):  
  10.         self .__name= carname  
  11.     def drive(self):  
  12.         print " Drive the New BMW as " + self.__name  
  13.   
  14. class NewBenz(Newcar):  
  15.     ''' Concrete Product '''  
  16.     def __init__(self,carname):  
  17.         self.__name= carname  
  18.     def drive(self):  
  19.         print " Drive the New Benz as " + self.__name  
  20.   
  21. class Oldcar:  
  22.     ''' Abstract Product '''  
  23.     def drive(self):  
  24.         pass  
  25.   
  26. class OldBMW(Oldcar):  
  27.     ''' Concrete Product '''  
  28.     def __init__(self,carname):  
  29.         self.__name= carname  
  30.     def drive(self):  
  31.         print " Drive the Old BMW as " + self. __name  
  32.   
  33. class OldBenz(Oldcar):  
  34.     ''' Concrete Product '''  
  35.     def __init__(self,carname):  
  36.         self.__name= carname  
  37.     def drive(self):  
  38.         print " Drive the Old Benz as " + self.__name  
  39.   
  40. class driver:  
  41.     ''' Abstract Factory also called Creator '''  
  42.     def driverNewCar(self):  
  43.         return Newcar()  
  44.     def driverOldCar(self):  
  45.         return Oldcar()  
  46.   
  47. class BMWdriver(driver ):  
  48.     ''' Concrete Factory or Creator '''  
  49.     def driverNewCar(self):  
  50.         return NewBMW( "NewBMW" )  
  51.     def driverOldCar(self):  
  52.         return OldBMW( "OldBMW" )  
  53.   
  54. class Benzdriver(driver) :  
  55.     ''' Concrete Factory or Creator '''  
  56.     def driverNewCar(self):  
  57.         return NewBenz( "NewBenz" )  
  58.     def driverOldCar(self):  
  59.         return OldBenz( "OldBenz" )  
  60.   
  61. if __name__ == "__main__" :  
  62.     driver= BMWdriver()  
  63.     car= driver.driverNewCar()  
  64.     car.drive()  
  65.     car= driver.driverOldCar()  
  66.     car.drive()  
  67.     driver= Benzdriver()  
  68.     car= driver.driverNewCar()  
  69.     car.drive()  
  70.     car= driver.driverOldCar()  
  71.     car.drive()  
Supplement 
[OO 設計模式] Simple Factory Pattern : 透過靜態方法來產生物件 
[OO 設計模式] Factory Method Pattern : 工廠方法模式 
[OO 設計模式] Gossip@DesignPattern : Creational - Abstract Factory 模式 
[OO 設計模式] Gossip@DesignPattern : Creational - Builder 模式

沒有留言:

張貼留言

[Git 常見問題] error: The following untracked working tree files would be overwritten by merge

  Source From  Here 方案1: // x -----删除忽略文件已经对 git 来说不识别的文件 // d -----删除未被添加到 git 的路径中的文件 // f -----强制运行 #   git clean -d -fx 方案2: 今天在服务器上  gi...