Python設計模式中的創建型工廠模式

一、工廠模式(Factory Pattern)

工廠模式(Factory Pattern),提供瞭一種實例化(創建)對象的最佳方式。

在工廠模式中,首先定義瞭一個抽象的工廠類(class Factory),並且在該工廠類中定義瞭提供瞭一個通用的、用於實例化對象的 Interface(接口)函數。然後當 Client 想要實例化某個具體的類的對象時,隻需要將需求告訴工廠類即可,由工廠類按需求去完成對象的實例化並返回。而 Client 作為調用者,則無需知道對象實例化的任何細節,這意味著任意的 Client 都無需要考慮根據對象的實例化細節來調整自身的代碼。

例如:當我們需要購買一批電腦,隻要把我們的需求告訴電腦工廠,電腦工廠就會幫我們把這批電腦做好,而不用我們自己去做這個電腦的,也不用我們自己去知道這個電腦是怎麼做出來的,這就是工廠模式。

工廠模式帶來的好處就是幫助我們把對象的實例化部分抽取瞭出來,目的是降低系統中代碼耦合度,並且增強瞭系統的擴展性。是一種解耦思想的實踐。

二、應用場景

  • Multi-Drivers(多驅動架構)

三、編碼示例

1、簡單工廠模式

簡單工廠模式,隻是做瞭一層簡單的封裝,將不同對象的實例化操作都單獨放到瞭一個工廠類中。

當我們需要實例化某個對象時,隻需把我們的需求告訴簡單工廠類,然後由這個簡單工廠類根據我們的需求去創建對應的對象即可。適用於簡單的業務場景。

優點: 簡單工廠模式可以根據需求,動態生成使用者所需類的對象,而使用者不用去知道怎麼創建對象,使得各個模塊各司其職,降低瞭系統的耦合性。

缺點: 擴展性差,違背瞭開閉原則(開閉原則指的是:軟件實現應該對擴展開放,對修改關閉)。新增產品時,需要修改簡單工廠類的代碼。

實體角色:

  • 產品的抽象類
  • 具體的產品子類
  • 簡單工廠類
import abc

# 產品的抽象類
class Productor(metaclass=abc.ABCMeta):

    @abc.abstractmethod
    def product(self, car):
        pass
        
# 更具體的某個產品類,是產品抽象類的子類
class Xiaomi(Productor):
    """
    小米手機
    """
    def product(self, price):
        return f"制造一部小米手機,售價{price}元"
        
    def __repr__(self):
        return f"Xiaomi,{id(self)}" 
    
# 更具體的某個產品類,是產品抽象類的子類
class Huawei(Productor):
    """
    華為手機
    """
    def product(self, price):
        return f"制造一部華為手機,售價{price}元"
        
    def __repr__(self):
        return f"Huawei,{id(self)}" 
    
# 簡單工廠類
class PhoneBrandFactory:
    """
    簡單工廠
    """
    def create_productor(self, brand):
        if brand == "Xiaomi":
            return Xiaomi()
        if brand == "Huawei":
            return Huawei()
        else:
            raise TypeError(f"沒有名為{brand}的手機生產商。")
        

if __name__ == "__main__":
    # 通過簡單工廠類提供的接口函數來獲得某個具體的產品類的對象
    Xiaomi = PhoneBrandFactory().create_productor("Xiaomi")
    Huawei = PhoneBrandFactory().create_productor("Huawei")
    print(Xiaomi)
    print(Huawei)
    print(Xiaomi.product(2999))
    print(Huawei.product(5999))

2、工廠方法模式

工廠方法模式,工廠類派生瞭任意個子工廠類,每個子工廠類對應一個具體的產品類,則某個產品類的對象的實例化就交由這個子工廠類來完成。

工廠方法模式是簡單工廠模式的改進,當我們需要擴展一個新產品時,隻需要擴展一個新的子工廠類即可,而不用去修改工廠類原有的代碼,這樣就符合瞭開閉原則。

優點: 擴展性好,符合瞭開閉原則。新增一種產品時,隻需增加改對應的產品類和對應的工廠子類即可。同時,也使得每個產品類和對應的工廠子類符合瞭單一職責原則,每個工廠隻負責一種產品,而不是由一個工廠去生成所有商品。

缺點: 當我們新增產品時,還需要提供對應的工廠類,系統中類的個數將會成倍增加,相當於增加瞭系統的復雜性。

實體角色:

  • 產品的抽象類
  • 具體的產品子類
  • 工廠類
  • 具體的工廠子類
import abc

# 產品的抽象類
class Productor(metaclass=abc.ABCMeta):
    @abc.abstractmethod
    def product(self, car):
        pass
        
# 更具體的某個產品類,是產品抽象類的子類
class Xiaomi(Productor):
    """
    小米手機
    """
    def product(self, price):
        return f"制造一部小米手機,售價{price}元"
        
    def __repr__(self):
        return f"Xiaomi,{id(self)}" 
    
# 更具體的某個產品類,是產品抽象類的子類
class Huawei(Productor):
    """
    華為手機
    """
    def product(self, price):
        return f"制造一部華為手機,售價{price}元"
        
    def __repr__(self):
        return f"Huawei,{id(self)}" 
    
# 工廠類
class PhoneBrandFactory(metaclass=abc.ABCMeta):
    """
    抽象工廠
    """
    @abc.abstractmethod
    def create_productor(self, brand):
        pass
    
# 具體產品對應的子工廠類
class XiaomiFactory(PhoneBrandFactory):
    def create_productor(self):
        return Xiaomi()
    
# 具體產品對應的子工廠類
class HuaweiFactory(PhoneBrandFactory):
    def create_productor(self):
        return Huawei()


if __name__ == "__main__":
    # 由這個子工廠類來完成對應的某個產品類的對象實例化
    Xiaomi = XiaomiFactory().create_productor()
    Huawei = HuaweiFactory().create_productor()
    print(Xiaomi)
    print(Huawei)
    print(Xiaomi.product(2999))
    print(Huawei.product(5999))

3、抽象工廠模式

抽象工廠模式,又是工廠方法模式的改進。工廠方法模式解決的是生產不同品牌的同一類型的電腦,而抽象工廠模式解決的是生產不同品牌的多種類型的電腦。

比如,工廠方法模式中的電腦工廠隻能生產老式的臺式電腦,而如果現在需要生產臺式電腦,筆記本電腦,平板電腦等多個種類的電腦的話,那麼工廠方法模式就不太方便瞭。而抽象工廠模式可以解決電腦工廠生產多個種類電腦的問題,也就是解決一個工廠生產多種類型的產品的問題。

如果我們需要臺式電腦,又需要筆記本電腦,要多種產品時,工廠方法模式無法滿足我們的需求;而抽象方法模式,提前在抽象工廠中,定義好瞭可能需要的多種產品,比如:臺式電腦,筆記本電腦,平板電腦等,當有需求的時候,我們隻需要創建相關子類和相關子工廠類即可。

優點: 抽象工廠類創建瞭多個類型的產品,當有需求時,可以創建相關子產品類和子工廠類來獲取。也就是可以滿足生產不同品牌的不同類型的電腦。

缺點: 擴展新種類產品時困難。抽象工廠模式需要我們在工廠抽象類中提前確定瞭可能需要的產品種類,以滿足不同品牌的多種產品的需求。但是如果我們需要的產品種類並沒有在工廠抽象類中提前確定,那我們就需要去修改工廠抽象類瞭,而一旦修改瞭工廠抽象類,那麼所有的工廠子類也需要修改,這樣顯然擴展不方便。

實體角色:

  • 產品功能特性抽象類
  • 具體的產品功能特性子類
  • 產品的抽象類
  • 具體的產品子類
  • 抽象工廠類
import abc

# 產品功能特性抽象類
class PhoneShell(metaclass=abc.ABCMeta):
    @abc.abstractmethod
    def shell(self):
        pass
   
class Cpu(metaclass=abc.ABCMeta):
    @abc.abstractmethod
    def cpu(self):
        pass
     
class OS(metaclass=abc.ABCMeta):
    @abc.abstractmethod
    def system(self):
        pass
    
# 具體的產品功能特性類
class SmallShell(PhoneShell):
    @property
    def shell(self):
        return "小屏幕"

class BigShell(PhoneShell):
    @property
    def shell(self):
        return "大屏幕"
    
class SnapDragonCpu(Cpu):
    @property
    def cpu(self):
        return "驍龍cpu"
        
class AppleCpu(Cpu):
    @property
    def cpu(self):
        return "蘋果cpu"
        
class Android(OS):
    @property
    def system(self):
        return "安卓系統"    
    
class IOS(OS):
    @property
    def system(self):
        return "IOS系統"
    
# 產品的抽象類
class ProductPhone:
    
    def __init__(self, factory):
        self.factory = factory()
        
    def product(self):
        self.shell = self.factory.product_shell()
        self.cpu = self.factory.product_cpu()
        self.OS = self.factory.product_system()
    
    def show_info(self):
        print(f"{self.factory}", f"配置信息:{self.shell.shell}, {self.cpu.cpu}, {self.OS.system}")
            
# 具體的產品子類
class XiaomiFactory(PhoneFactory):
    def product_shell(self):
        return BigShell()
    
    def product_cpu(self):
        return SnapDragonCpu()
    
    def product_system(self):
        return Android()
    
    def __repr__(self):
        return "小米手機,售價2999!"
        
class IphoneFactory(PhoneFactory):
    def product_shell(self):
        return SmallShell()
    
    def product_cpu(self):
        return AppleCpu()
    
    def product_system(self):
        return IOS()
    
    def __repr__(self):
        return "蘋果手機,售價8999!"
    
# 抽象工廠類
class PhoneFactory(metaclass=abc.ABCMeta):
    @abc.abstractmethod
    def product_shell(self):
        pass
    
    @abc.abstractmethod
    def product_cpu(self):
        pass
    
    @abc.abstractmethod
    def product_system(self):
        pass 

        
if __name__ == "__main__":
    xiaomi = ProductPhone(XiaomiFactory)
    xiaomi.product()
    xiaomi.show_info()
    
    iphone = ProductPhone(IphoneFactory)
    iphone.product()
    iphone.show_info()

到此這篇關於Python設計模式中的創建型工廠模式的文章就介紹到這瞭,更多相關Python工廠模式內容請搜索WalkonNet以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持WalkonNet!

推薦閱讀: