1. 程式人生 > >簡單工廠模式(python版)

簡單工廠模式(python版)

什麼是簡單工廠模式


工廠模式有一種非常形象的描述,建立物件的類就如一個工廠,而需要被建立的物件就是一個個產品;在工廠中加工產品,使用產品的人,不用在乎產品是如何生產出來的。從軟體開發的角度來說,這樣就有效的降低了模組之間的耦合。

簡單工廠的作用是例項化物件,而不需要客戶瞭解這個物件屬於哪個具體的子類。簡單工廠例項化的類具有相同的介面或者基類,在子類比較固定並不需要擴充套件時,可以使用簡單工廠。如資料庫生產工廠就是簡單工廠的一個應用

採用簡單工廠的優點是可以使使用者根據引數獲得對應的類例項,避免了直接例項化類,降低了耦合性;缺點是可例項化的型別在編譯期間已經被確定,如果增加新類 型,則需要修改工廠,不符合OCP(開閉原則)的原則。簡單工廠需要知道所有要生成的型別,當子類過多或者子類層次過多時不適合使用。

簡單工廠模式實現


下面考慮《大話設計模式》中的一個例子:

題目:用任意一種面嚮物件語言實現一個計算器控制檯程式。要求輸入兩個數和運算子號,得到結果。

題目分析:
程式應該做到:(1)可維護;(2)可複用;(3)可擴充套件;(4)靈活性好。
可維護:就是說程式碼一處更改,不能產生連鎖反應,不能影響其他地方。
可複用:儘量減少重複性程式碼。
可擴充套件:如果要擴充套件新的功能、新的業務,則只需要增加新的類就好了,不對已有的類和邏輯產生影響。插拔式的應用。

面向物件要點:
面向物件三大特性:封裝、繼承、多型。
通過封裝、繼承、多型把程式耦合降低。
業務邏輯和介面邏輯分開。

類的結構圖:


程式碼實現:
1. 首先,搞清楚業務中容易發生變化的部分。在本應用中,要求計算兩個數的運算結果,那麼要進行什麼樣的運算,這就是一個容易發生變化的部分。例如,我們現在只想實現加減乘除運算,後期又想增加開根或者求餘運算。那麼如何應對這種需求帶來的變化。在程式設計的時候就應該考慮到程式的可維護性、可擴充套件性、程式碼的可複用性、靈活性等等。
 
2. 例如現在這個運算器只有加減乘除四種運算。首先建一個Operation類,這個類是各種具體運算類(加減乘除)的父類,主要是接受使用者輸入的數值。該類如下:

class Operation():
    def __init__(self,NumberA=0,NumberB=0):
        self.NumberA = NumberA
        self.NumberB = NumberB
 
    def GetResult(self):
        pass

3. 然後是具體的運算類:Add、Sub、Mul、Div。他們都繼承了Operation類,並且重寫了getResult()方法。這樣就可以用多型性降低不同業務邏輯的耦合度,修改任何一種運算類都不會影響其他的運算類。具體類的程式碼如下:
 

class AddOp(Operation):
    def GetResult(self):
        return self.NumberB + self.NumberA
 
class MinusOp(Operation):
    def GetResult(self):
        return self.NumberA - self.NumberB
 
class MultiOp(Operation):
    def GetResult(self):
        return self.NumberA * self.NumberB
 
class DivideOp(Operation):
    def GetResult(self):
        try:
            return 1.0*self.NumberA / self.NumberB
        except ZeroDivisionError:
            raise


4.  那麼如何讓計算器知道我是要用哪一種運算呢?也就是說到底要例項化哪一個具體的運算類,Add?Sub?Mul?Div?這時就應該考慮用 一個單獨的類來做這個創造具體例項的過程,這個類就是工廠類。如下:

 

class OperationFatory():
    def ChooseOperation(self,op):
        if op == '+':
            return AddOp()
        if op == '-':
            return MinusOp()
        if op == '*':
            return MultiOp()
        if op == '/':
            return DivideOp()


5. 這樣,使用者只要輸入運算子,工廠類就可以建立合適的例項,通過多型性,即返回給父類的方式實現運算結果。客戶端程式碼如下:

if __name__ == '__main__':
    ch = ''
    while not ch=='q': 
        NumberA = eval(raw_input('Please input number1:  '))
        op = str(raw_input('Please input the operation:  '))
        NumberB = eval(raw_input('Please input number2:  '))
        OPFactory = OperationFatory()
        OPType = OPFactory.ChooseOperation(op)
        OPType.NumberA = NumberA
        OPType.NumberB = NumberB
        print 'The result is:',OPType.GetResult()
        print '\n#--  input q to exit any key to continue'
        try:
            ch = str(raw_input())
        except:
            ch = ''

完整版程式碼如下:

# -*-coding:UTF-8-*-  
from abc import ABCMeta,abstractmethod
 
class Operation():
    def __init__(self,NumberA=0,NumberB=0):
        self.NumberA = NumberA
        self.NumberB = NumberB
 
    def GetResult(self):
        pass
 
class AddOp(Operation):
    def GetResult(self):
        return self.NumberB + self.NumberA
 
class MinusOp(Operation):
    def GetResult(self):
        return self.NumberA - self.NumberB
 
class MultiOp(Operation):
    def GetResult(self):
        return self.NumberA * self.NumberB
 
class DivideOp(Operation):
    def GetResult(self):
        try:
            return 1.0*self.NumberA / self.NumberB
        except ZeroDivisionError:
            raise
 
class OperationFatory():
    def ChooseOperation(self,op):
        if op == '+':
            return AddOp()
        if op == '-':
            return MinusOp()
        if op == '*':
            return MultiOp()
        if op == '/':
            return DivideOp()
 
if __name__ == '__main__':
    ch = ''
    while not ch=='q': 
        NumberA = eval(raw_input('Please input number1:  '))
        op = str(raw_input('Please input the operation:  '))
        NumberB = eval(raw_input('Please input number2:  '))
        OPFactory = OperationFatory()
        OPType = OPFactory.ChooseOperation(op)
        OPType.NumberA = NumberA
        OPType.NumberB = NumberB
        print 'The result is:',OPType.GetResult()
        print '\n#--  input q to exit any key to continue'
        try:
            ch = str(raw_input())
        except:
            ch = ''

---------------------  
來源:CSDN 
原文:https://blog.csdn.net/u014148798/article/details/52242411