建立型模式

  建立型模式:工廠方法模式、抽象工廠模式、建立者模式、原型模式、單例模式。
python

1、簡單工廠模式

  不直接向客戶端暴露對象建立的實現細節,而是經過一個工廠類來負責建立產品類的實例。該模式不屬於23種設計模式之一。shell

一、簡單工程模式示例

from abc import ABCMeta, abstractmethod

class Payment(metaclass=ABCMeta):
    # abstract class
    @abstractmethod
    def pay(self, money):
        pass

class Alipay(Payment):
    def __init__(self, use_huabei=False):
        self.use_huabei = use_huabei

    def pay(self, money):
        if self.use_huabei:
            print('支付寶支付%d元' % money)
        else:
            print('支付寶餘額支付%d元。' % money)

class WechatPay(Payment):
    def pay(self, money):
        print("微信支付%d元" % money)

class PaymentFactory:   # 工廠類:生產支付對象
    def create_payment(self, method):
        if method == 'alipay':
            return Alipay()
        elif method == 'wechat':
            return WechatPay()
        elif method == 'huabei':
            return Alipay(use_huabei=True)
        else:
            raise TypeError("No such payment named %s" % method)


pf = PaymentFactory()
# p = pf.create_payment('alipay')
p = pf.create_payment('huabei')   # 隱藏了類的內部實現,無需瞭解代碼邏輯
p.pay(100)

 

  Payment是抽象類,是爲了讓產品有一樣的表現,能夠一樣的對外使用。若是要增長新的支付,好比銀行支付,只要添加新的產品類便可。數據庫

二、簡單工廠模式總結

角色:設計模式

  • 工廠角色(Creator)
  • 抽象產品角色(Product)
  • 具體產品角色(Concrete Product)

優勢:微信

  • 隱藏了對象建立的實現細節
  • 客戶端不須要修改代碼

缺點:函數

  • 違反了單一職責原則,將建立邏輯集中到一個工廠類裏
  • 當添加新產品時,須要修改工廠類代碼,違反了開閉原則。

2、工廠方法模式

  定義一個用於建立對象的接口(工廠接口),讓子類決定實例化哪個產品類。微信支付

一、工廠方法模式示例

from abc import ABCMeta, abstractmethod

class Payment(metaclass=ABCMeta):   # 產品接口
    # abstract class
    @abstractmethod
    def pay(self, money):
        pass

class Alipay(Payment):    # 具體產品
    def __init__(self, use_huabei=False):
        self.use_huabei = use_huabei

    def pay(self, money):
        if self.use_huabei:
            print('支付寶支付%d元' % money)
        else:
            print('支付寶餘額支付%d元。' % money)

class WechatPay(Payment):
    def pay(self, money):
        print("微信支付%d元" % money)

class BankPay(Payment):   # 建立一個新產品
    def pay(self, money):
        print("銀行卡支付%d元" % money)

class PaymentFactory(metaclass=ABCMeta):   # 工廠類接口
    @abstractmethod
    def create_payment(self):
        pass

class AlipayFactory(PaymentFactory):   # 具體工廠類
    def create_payment(self):
        return Alipay()

class WechatPayFactory(PaymentFactory):
    def create_payment(self):
        return WechatPay()

class HuabeiFactory(PaymentFactory):
    def create_payment(self):
        return Alipay(use_huabei=True)

class BankPayFactory(PaymentFactory):   # 建立新產品對應的工廠
    def create_payment(self):
        return BankPay()

pf = HuabeiFactory()  # 建立工廠
p = pf.create_payment()
p.pay(100)

二、工廠方法模式總結

角色:ui

  • 抽象工廠角色(Creator)
  • 具體工廠角色(Concrete Creator)
  • 抽象產品角色(Product)
  • 具體產品角色(Concrete Product)

優勢:spa

  • 每一個具體產品都對應一個具體工廠類,不須要修改工廠類代碼
  • 隱藏了對象建立的實現細節

缺點:操作系統

  • 每增長一個具體產品類,就必須增長一個響應的具體工廠類(代碼太多了)

3、抽象工廠模式

  定義一個工廠類接口,讓工廠子類來建立一系列相關或相互依賴的對象。

一、抽象工廠模式示例

  例:生產一部手機,須要手機殼、CPU、操做系統三類對象進行組裝,其中每類對象都有不一樣的種類。對每一個具體工廠,分別生產一部手機所須要的三個對象。

from abc import abstractmethod, ABCMeta

# ------抽象產品------
class PhoneShell(metaclass=ABCMeta):  # 手機殼
    @abstractmethod
    def show_shell(self):
        pass

class CPU(metaclass=ABCMeta):   # cpu
    @abstractmethod
    def show_cpu(self):
        pass

class OS(metaclass=ABCMeta):   # 系統
    @abstractmethod
    def show_os(self):
        pass


# ------抽象工廠------
class PhoneFactory(metaclass=ABCMeta):  # 每一個工廠都生產一套產品
    @abstractmethod
    def make_shell(self):
        pass

    @abstractmethod
    def make_cpu(self):
        pass

    @abstractmethod
    def make_os(self):
        pass


# ------具體產品------
class SmallShell(PhoneShell):
    def show_shell(self):
        print("普通手機小手機殼")

class BigShell(PhoneShell):
    def show_shell(self):
        print("普通手機大手機殼")

class AppleShell(PhoneShell):
    def show_shell(self):
        print("蘋果手機殼")

class SnapDragonCPU(CPU):
    def show_cpu(self):
        print("驍龍CPU")

class MediaTekCPU(CPU):
    def show_cpu(self):
        print("聯發科CPU")

class AppleCPU(CPU):
    def show_cpu(self):
        print("蘋果CPU")

class Android(OS):
    def show_os(self):
        print("Android系統")

class IOS(OS):
    def show_os(self):
        print("iOS系統")


# ------具體工廠------
class MiFactory(PhoneFactory):  # 小米工廠
    def make_cpu(self):
        return SnapDragonCPU()

    def make_os(self):
        return Android()

    def make_shell(self):
        return BigShell()

class HuaweiFactory(PhoneFactory):   # 華爲工廠
    def make_cpu(self):
        return MediaTekCPU()

    def make_os(self):
        return Android()

    def make_shell(self):
        return SmallShell()

class IPhoneFactory(PhoneFactory):  # 蘋果工廠,一套組件還作了限制
    def make_cpu(self):
        return AppleCPU()    # 蘋果cpu

    def make_os(self):
        return IOS()   # 蘋果系統

    def make_shell(self):
        return AppleShell()   # 蘋果手機殼


# ------客戶端------
class Phone:   # 手機
    def __init__(self, cpu, os, shell):
        self.cpu = cpu
        self.os = os
        self.shell = shell

    def show_info(self):
        print("手機信息:")
        self.cpu.show_cpu()
        self.os.show_os()
        self.shell.show_shell()

def make_phone(factory):
    cpu = factory.make_cpu()
    os = factory.make_os()
    shell = factory.make_shell()
    return Phone(cpu, os, shell)  # 生成手機對象


p1 = make_phone(IPhoneFactory())   # 生成一個蘋果手機對象
p1.show_info()

  相比工廠方法模式,抽象工廠模式中每一個具體工廠都生產一套產品

二、抽象工廠模式總結

角色:

  • 抽象工廠角色(Creator)
  • 具體工廠角色(Concrete Creator)
  • 抽象產品角色(Product)
  • 具體產品角色(Concrete Product)
  • 客戶端(Client)

優勢:

  • 客戶端類的具體實現相分離
  • 每一個工廠建立了一個完整的產品系列,使得易於交換產品系列
  • 有利於產品的一致性(即產品之間的約束關係)

缺點:

  • 難以支持新種類的(抽象)產品:好比在CPU、手機殼、系統外再加一個內存,就很是難添加,該模式不多會用到。

4、建立者(建造者)模式

  將一個複雜對象的構建與它的表示分離,使得一樣的構建過程能夠建立不一樣的表示。

一、建造者模式示例

from abc import ABCMeta, abstractmethod

class Player:  # 產品:遊戲角色
    def __init__(self, face=None, body=None, arm=None, leg=None):   # 傳入初始化參數
        self.face = face
        self.body = body
        self.arm = arm
        self.leg = leg

    def __str__(self):
        return "%s, %s, %s, %s" % (self.face, self.body, self.arm, self.leg)


class PlayerBuilder(metaclass=ABCMeta):  # 抽象建造者:抽象類做爲接口
    @abstractmethod
    def build_face(self):
        pass

    @abstractmethod
    def build_body(self):
        pass

    @abstractmethod
    def build_arm(self):
        pass

    @abstractmethod
    def build_leg(self):
        pass


class SexyGirlBuilder(PlayerBuilder):  # 具體建立者:女性角色
    def __init__(self):
        self.player = Player()   # 玩家

    def build_face(self):
        self.player.face = "漂亮臉蛋"

    def build_body(self):
        self.player.body = "苗條"

    def build_arm(self):
        self.player.arm = "漂亮胳膊"

    def build_leg(self):
        self.player.leg = "大長腿"


class Monster(PlayerBuilder):   # 具體建立者:怪物
    def __init__(self):
        self.player = Player()

    def build_face(self):
        self.player.face = "怪獸臉"   # 被隱藏的產品內部結構,也是表示代碼

    def build_body(self):
        self.player.body = "怪獸身材"  # 被隱藏的產品內部結構,也是表示代碼

    def build_arm(self):
        self.player.arm = "長毛的胳膊"

    def build_leg(self):
        self.player.leg = "長毛的腿"


class PlayerDirector:    # 指揮者:控制組裝順序
    def build_player(self, builder):
        builder.build_body()  # 被隱藏的裝配過程,也是構造代碼
        builder.build_face()  # 被隱藏的裝配過程,也是構造代碼
        builder.build_arm()
        builder.build_leg()
        return builder.player


# client調用
# builder = SexyGirlBuilder()   # 建立一個性感女孩builder
builder = Monster()    # 建立一個怪物builder
director = PlayerDirector()  # 指揮者實例化
p = director.build_player(builder)   # 組裝建立(不一樣角色建立函數都是相同的)
print(p)

  

二、建造者模式總結

角色:

  • 抽象建造者(Builder)
  • 具體建造者(Concrete Builder)
  • 指揮者(Director)
  • 產品(Product)

優勢:

  • 隱藏了一個產品的內部結構和裝配過程
  • 將構造代碼與表示代碼分開
  • 能夠對構造過程進行更精細的控制

建造者模式與抽象工廠模式對比:

  建造者模式與抽象工廠模式類似,也用來建立複雜對象。主要區別是建造者模式着重一步步構造一個複雜對象(控制它的順序),而抽象工廠模式着重於多個系列的產品對象。

5、單例模式

  保證一個類只有一個實例,並提供一個訪問它的全局訪問點。

一、單例模式示例

from abc import abstractmethod, ABCMeta

# 經過 __new__ 方法是實現單例模式的的一種方式,若是實例對象存在了就直接返回該實例便可,若是尚未,那麼就先建立一個實例,再返回。
class Singleton:
    def __new__(cls, *args, **kwargs):
        if not hasattr(cls, "_instance"):  # 反射查看是否有_instance的類屬性
            cls._instance = super(Singleton, cls).__new__(cls)   # 調用父類的__new__方法來建立實例
        return cls._instance

class MyClass(Singleton):
    def __init__(self, a):
        self.a = a


a = MyClass(10)
b = MyClass(20)

print(a.a)  # 輸出20
print(b.a)  # 輸出20

print(id(a), id(b))   # 4400380840 4400380840, id相同說明二者是同一個實例

# 常應用於日誌文件對象,數據庫鏈接器對象,操做系統文件對象等狀況使用。

  

二、單例模式總結

角色:

  • 單例(Singleton):全部它的子類都知足單例模式

優勢:

  • 對惟一示例的受控訪問
  • 單例至關於全局變量,但防止了命名空間被污染(一個名字是全局變量時,在整個命名空間裏這個名字就被佔用了,再使用這個名字會衝突)

6、建立型模式小結

  抽象工廠模式和建造者模式相比於簡單工廠模式和工廠方法模式而言更靈活也更復雜。

  一般狀況下、設計以簡單工廠模式或工廠方法模式開發,當你發現設計須要更大的靈活性時,則向更復雜的設計模式演化。

相關文章
相關標籤/搜索