1. 程式人生 > >總結工廠模式---簡單工廠、工廠方法、抽象工廠

總結工廠模式---簡單工廠、工廠方法、抽象工廠

ati tac 自己的 object 獲得 抽象工廠 nbsp art 工廠類

簡單工廠

首先,我們先看一個簡單工廠的例子:

#coding=utf-8
class Mercedes(object):
    """梅賽德斯
    """
    def __repr__(self):
        return "Mercedes-Benz"

class BMW(object):
    """寶馬
    """
    def __repr__(self):
        return "BMW"

假設我們有兩個“產品”分別是Mercedes和BMW的汽車,如果沒有“工廠”來生產它們,我們就要在代碼中自己進行實例化,如:
mercedes = Mercedes()
bmw = BMW()

  

但現實中,你可能會面對很多汽車產品,而且每個產品的構造參數還不一樣,這樣在創建實例時會遇到麻煩。這時就可以構造一個“簡單工廠”把所有汽車實例化的過程封裝在裏面。

class SimpleCarFactory(object):
    """簡單工廠
    """
    @staticmethod
    def product_car(name):
        if name == ‘mb‘:
            return Mercedes()
        elif name == ‘bmw‘:
            return BMW()

  

有了SimpleCarFactory

類後,就可以通過向固定的接口傳入參數獲得想要的對象實例,如下:

c1 = SimpleCarFactory.product_car(mb)
c2 = SimpleCarFactory.product_car(bmw)

工廠方法

雖然有了一個簡單的工廠,但在實際使用工廠的過程中,我們會發現新問題:如果我們要新增一個“產品”,例如Audi的汽車,我們除了新增一個Audi類外還要修改SimpleCarFactory內的product_car方法。這樣就違背了軟件設計中的開閉原則,即在擴展新的類時,盡量不要修改原有代碼。所以我們在簡單工廠的基礎上把SimpleCarFactory

抽象成不同的工廠,每個工廠對應生成自己的產品,這就是工廠方法

#coding=utf-8
import abc

class AbstractFactory(object):
    """抽象工廠
    """
    __metaclass__ = abc.ABCMeta

    @abc.abstractmethod
    def product_car(self):
        pass

class MercedesFactory(AbstractFactory):
    """梅賽德斯工廠
    """
    def product_car(self):
        return Mercedes()

class BMWFactory(AbstractFactory):
    """寶馬工廠
    """
    def product_car(self):
        return BMW()
"""
我們把工廠抽象出來用abc模塊 實現了一個抽象的基類AbstractFactory
這樣就可以通過特定的工廠來獲得特定的產品實例了:
"""
c1 = MercedesFactory().product_car()
c2 = BMWFactory().product_car()


  

每個工廠負責生產自己的產品也避免了我們在新增產品時需要修改工廠的代碼,而只要增加相應的工廠即可。如新增一個Audi產品,只需新增一個Audi類和AudiFactory類。

抽象工廠

工廠方法雖然解決了我們“修改代碼”的問題,但如果我們要生產很多產品,就會發現我們同樣需要寫很多對應的工廠類。比如如果MercedesFactoryBMWFactory不僅生產小汽車,還要生產SUV,那我們用工廠方法就要再多構造兩個生產SUV的工廠類。所以為了解決這個問題,我們就要再更進一步的抽象工廠類,讓一個工廠可以生產同一類的多個產品,這就是抽象工廠。具體實現如下

#coding=utf-8
import abc

# 兩種小汽車
class Mercedes_C63(object):
    """梅賽德斯 C63
    """
    def __repr__(self):
        return "Mercedes-Benz: C63"

class BMW_M3(object):
    """寶馬 M3
    """
    def __repr__(self):
        return "BMW: M3"

# 兩種SUV
class Mercedes_G63(object):
    """梅賽德斯 G63
    """
    def __repr__(self):
        return "Mercedes-Benz: G63"

class BMW_X5(object):
    """寶馬 X5
    """
    def __repr__(self):
        return "BMW: X5"

class AbstractFactory(object):
    """抽象工廠
    可以生產小汽車外,還可以生產SUV
    """
    __metaclass__ = abc.ABCMeta

    @abc.abstractmethod
    def product_car(self):
        pass

    @abc.abstractmethod
    def product_suv(self):
        pass

class MercedesFactory(AbstractFactory):
    """梅賽德斯工廠
    """
    def product_car(self):
        return Mercedes_C63()

    def product_suv(self):
        return Mercedes_G63()

class BMWFactory(AbstractFactory):
    """寶馬工廠
    """
    def product_car(self):
        return BMW_M3()

    def product_suv(self):
        return BMW_X5()

我們讓基類AbstractFactory同時可以生產汽車和SUV,然後令MercedesFactoryBMWFactory繼承AbstractFactory並重寫product_car和product_suv方法即可。

c1 = MercedesFactory().product_car()
s1 = MercedesFactory().product_suv()
print(c1, s1)
s2 = BMWFactory().product_suv()
c2 = BMWFactory().product_car()
print(c2, s2)

  

抽象工廠模式與工廠方法模式最大的區別在於,抽象工廠中的一個工廠對象可以負責多個不同產品對象的創建 ,這樣比工廠方法模式更為簡單、有效率

結論

初學設計模式時會對三種工廠模式的實際應用比較困惑,其實三種模式各有優缺點,應用的場景也不盡相同:

  • 簡單工廠模式適用於需創建的對象較少,不會造成工廠方法中的業務邏輯太過復雜的情況下,而且用戶只關心那種類型的實例被創建,並不關心其初始化過程時,比如多種數據庫(MySQL/MongoDB)的實例,多種格式文件的解析器(XML/JSON)等。
  • 工廠方法模式繼承了簡單工廠模式的優點又有所改進,其不再通過一個工廠類來負責所有產品的創建,而是將具體創建工作交給相應的子類去做,這使得工廠方法模式可以允許系統能夠更高效的擴展。實際應用中可以用來實現系統的日誌系統等,比如具體的程序運行日誌,網絡日誌,數據庫日誌等都可以用具體的工廠類來創建。
  • 抽象工廠模式在工廠方法基礎上擴展了工廠對多個產品創建的支持,更適合一些大型系統,比如系統中有多於一個的產品族,且這些產品族類的產品需實現同樣的接口,像很多軟件系統界面中不同主題下不同的按鈕、文本框、字體等等。

總結工廠模式---簡單工廠、工廠方法、抽象工廠