Python之工廠模式


一、介紹

工廠模式(Factory Pattern)是最常用的設計模式之一,這種類型的設計模式屬於創建型模式,它提供了一種創建對象的最佳方式。

在工廠模式中,我們在創建對象時不會對客戶端暴露創建邏輯,並且是通過使用一個共同的接口來指向新創建的對象。

意圖:定義一個創建對象的接口,讓其子類自己決定實例化哪一個工廠類,工廠模式使其創建過程延遲到子類進行。

主要解決:主要解決接口選擇的問題。

何時使用:我們明確地計划不同條件下創建不同實例時。

 

二、簡單工廠

統一使用一個類作為對外接口,根據參數的不同,去選擇實例化不同的類。

"""
兩個產品(兩種類型的書)
"""


class TechnicalBooks(object):
    """技術書籍"""

    def publish(self):
        return "Python-Book"


class LiteraryBooks(object):
    """文學書籍"""

    def publish(self):
        return "Black Hole Book"


# 現在我們有兩種類型的書,分別是TechnicalBooks和LiteraryBooks的書
# 按照我們平常的方法來實例化的話,此時創建對象時是會對客戶端暴露真正創建的類
it_books = TechnicalBooks()
ly_books = LiteraryBooks()


# 這時我們就可以構造一個"簡單工廠"把所有實例化的過程封裝在里面,把真正實例的類隱藏起來
class SimpleFactory(object):
    """簡單工廠"""

    @staticmethod
    def publish_book(name):
        if name == 'technical':
            return TechnicalBooks()
        elif name == 'literary':
            return LiteraryBooks()


it_books2 = SimpleFactory.publish_book('technical')
ly_books2 = SimpleFactory.publish_book('literary')

簡單工廠的好處在於,把不同類的實例化統一到一個"工廠",即不對外暴露真正的創建類,也提供了一個對外的統一接口。

但是簡單工廠也有一個缺點,那就是違背了solid的 "開閉原則",假如我們還需要增加一種書籍,那就必須要對簡單工廠SimpleFactory進行源碼的修改,

簡單工廠使用場景:

  • 已經確定有多少具體的類,不會再增加的情況下使用。

例如:某個系統,已經明確就只會有MySQL、Redis、MongoDB三個數據庫的情況下,可以直接使用簡單工廠模式。

 

三、工廠方法

上面的簡單工廠我們已經知道了,如果新增一些類型的時候會違背軟件設計中的開閉原則,但是我們希望在擴展新的類時,不要修改原有的代碼。這個時候我們可以在簡單工廠的基礎上把SimpleFactory抽象成不同的工廠,每個工廠對應生成自己的產品,這就是工廠方法。

"""
兩個產品(兩種類型的書)
"""
import abc


# 真正進行實例化的類
class TechnicalBooks(object):
    """技術書籍"""

    def publish(self):
        return "Python-Book"


class LiteraryBooks(object):
    """文學書籍"""

    def publish(self):
        return "Black Hole Book"


# 抽象工廠:先定義抽象類,然后每種類型的書籍都有自己對於的工廠
class AbstractFactory(metaclass=abc.ABCMeta):
    """抽象工廠"""

    @abc.abstractmethod
    def publish_book(self):
        pass


class TechnicalFactory(AbstractFactory):
    """技術書籍工廠"""

    def publish_book(self):
        return TechnicalBooks()


class LiteraryFactory(AbstractFactory):
    """文學書籍工廠"""

    def publish_book(self):
        return LiteraryBooks()


it_books2 = TechnicalFactory().publish_book()
ly_books2 = LiteraryFactory().publish_book()

這樣每個工廠就只負責生產自己的產品,避免了在新增產品時需要修改工廠的代碼,遵循了"開閉原則",如果需要新增產品時,只需要增加相應的工廠即可。

比如要新增一種小說類型的書籍,只需新增一個NovelBooks類和NovelFactory類。

工廠方法的使用場景

  • 當系統中擁有的子類很多,並且以后可能還需要不斷拓展增加不同的子類時。
  • 當設計系統時,還不能明確具體有哪些類時。

在工廠方法中,使用者不需要知道具體的產品類名,只需要知道其對應的工廠即可。

 

四、抽象工廠

工廠方法解決了"開閉原則"的問題,但是我們出版書籍之前肯定還會有其他的步驟,比如印刷。
如果每一個步驟我們就要寫一個對應的工廠類,那我們就會需要創建很多很多類了。
因此為了解決這個問題,我們就要需要抽象工廠類,讓一個工廠可以生產同一類的多個產品或多個動作(步驟),這就是抽象工廠。

"""
兩個產品(兩種類型的書)
"""
import abc


# 印刷書籍
class PrintingTechnicalBooks(object):
    """印刷技術書籍"""

    def printing(self):
        return "Print-Python-Book"


class PrintingLiteraryBooks(object):
    """印刷文學書籍"""

    def printing(self):
        return "Print Black Hole Book"


# 出版書籍
class TechnicalBooks(object):
    """出版技術書籍"""

    def publish(self):
        return "Python-Book"


class LiteraryBooks(object):
    """出版文學書籍"""

    def publish(self):
        return "Black Hole Book"


# 抽象工廠:先定義抽象類,然后每種類型的書籍都有自己對於的工廠
class AbstractFactory(metaclass=abc.ABCMeta):
    """抽象工廠"""

    @abc.abstractmethod
    def print_book(self):
        pass

    @abc.abstractmethod
    def publish_book(self):
        pass


class TechnicalFactory(AbstractFactory):
    """技術書籍工廠"""

    def print_book(self):
        return PrintingTechnicalBooks()

    def publish_book(self):
        return TechnicalBooks()


class LiteraryFactory(AbstractFactory):
    """文學書籍工廠"""

    def print_book(self):
        return PrintingLiteraryBooks()

    def publish_book(self):
        return LiteraryBooks()


# 實例化工廠對象
it = TechnicalFactory()
ly = LiteraryFactory()

# 印刷書籍
it_print = it.print_book()
ly_print = ly.print_book()
# 出版書籍
it_publish = it.publish_book()
ly_publish = ly.publish_book()

抽象工廠模式與工廠方法模式的區別:

    抽象工廠中的一個工廠對象可以負責多個不同產品對象的創建 

 

抽象工廠的使用場景

  • 當多個產品(步驟)集合在一起,組成產品族時。
  • 對於一個產品族,如果只想顯示接口而不是實現時。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM