1. 程式人生 > >算法3-設計模式

算法3-設計模式

create edi cme 實例化 pri new 命名 實體 父類

設計模式六大原則

1、開閉原則:一個軟件實體如類、模塊和函數應該對擴展開放,對修改關閉。即軟件實體應盡量在不修改原有代碼的情況下進行擴展。

2、裏氏(Liskov)替換原則:所有引用基類(父類)的地方必須能透明地使用其子類的對象。

3、依賴倒置原則:高層模塊不應該依賴低層模塊,二者都應該依賴其抽象;抽象不應該依賴細節;細節應該依賴抽象。換言之,要針對接口編程,而不是針對實現編程。

4、接口隔離原則:使用多個專門的接口,而不使用單一的總接口,即客戶端不應該依賴那些它不需要的接口。

5、迪米特法則:一個軟件實體應當盡可能少地與其他實體發生相互作用。

6、單一職責原則:不要存在多於一個導致類變更的原因。通俗的說,即一個類只負責一項職責。

技術分享圖片
內容:不直接向客戶端暴露對象創建的實現細節,而是通過一個工廠類來負責創建產品類的實例。
角色:
工廠角色(Creator)
抽象產品角色(Product)
具體產品角色(Concrete Product)
優點:
隱藏了對象創建的實現細節
客戶端不需要修改代碼
缺點:
違反了單一職責原則,將創建邏輯幾種到一個工廠類裏
當添加新產品時,需要修改工廠類代碼,違反了開閉原則
簡單工廠模式 技術分享圖片
from abc import abstractmethod, ABCMeta


class Payment(metaclass=ABCMeta):
    @abstractmethod
    
def pay(self, money): raise NotImplementedError class Alipay(Payment): def __init__(self, enable_yuebao=False): self.enable_yuebao = enable_yuebao def pay(self, money): if self.enable_yuebao: print("余額寶支付%s元" % money) else: print("支付寶支付%s元
" % money) class ApplePay(Payment): def pay(self, money): print("蘋果支付%s元" % money) class PaymentFactory: # 工廠類 封裝了對象創建的細節 def create_payment(self, method): if method == "alipay": return Alipay() elif method == "applepay": return ApplePay() elif method == "yuebao": return Alipay(True) else: raise NameError(method) factory = PaymentFactory() payment = factory.create_payment("yuebao") payment.pay(100)
代碼示例

技術分享圖片
內容:定義一個用於創建對象的接口(工廠接口),讓子類決定實例化哪一個產品類。
角色:
抽象工廠角色(Creator)
具體工廠角色(Concrete Creator)
抽象產品角色(Product)
具體產品角色(Concrete Product)

工廠方法模式相比簡單工廠模式將每個具體產品都對應了一個具體工廠。

適用場景:
需要生產多種、大量復雜對象的時候
需要降低耦合度的時候
當系統中的產品種類需要經常擴展的時候
優點:
每個具體產品都對應一個具體工廠類,不需要修改工廠類代碼
隱藏了對象創建的實現細節
缺點:
每增加一個具體產品類,就必須增加一個相應的具體工廠類
工廠方法模式 技術分享圖片
from abc import abstractmethod, ABCMeta


class Payment(metaclass=ABCMeta):
    @abstractmethod
    def pay(self, money):
        raise NotImplementedError


class Alipay(Payment):
    def pay(self, money):
        print("支付寶支付%s元" % money)


class ApplePay(Payment):
    def pay(self, money):
        print("蘋果支付%s元"%money)


class PaymentFactory(metaclass=ABCMeta):
    @abstractmethod
    def create_payment(self):
        pass


class AlipayFactory(PaymentFactory):
    def create_payment(self):
        return Alipay()

class ApplePayFactory(PaymentFactory):
    def create_payment(self):
        return ApplePay()




# 用戶輸入
# 支付寶,120

af = AlipayFactory()
ali = af.create_payment()
ali.pay(120)
示例代碼

技術分享圖片
內容:定義一個工廠類接口,讓工廠子類來創建一系列相關或相互依賴的對象。
例:生產一部手機,需要手機殼、CPU、操作系統三類對象進行組裝,其中每類對象都有不同的種類。對每個具體工廠,分別生產一部手機所需要的三個對象。
角色:
抽象工廠角色(Creator)
具體工廠角色(Concrete Creator)
抽象產品角色(Product)
具體產品角色(Concrete Product)
客戶端(Client)
相比工廠方法模式,抽象工廠模式中的每個具體工廠都生產一套產品。
適用場景:
系統要獨立於產品的創建與組合時
強調一系列相關的產品對象的設計以便進行聯合使用時
提供一個產品類庫,想隱藏產品的具體實現時
優點:
將客戶端與類的具體實現相分離
每個工廠創建了一個完整的產品系列,使得易於交換產品系列
有利於產品的一致性(即產品之間的約束關系)
缺點:
難以支持新種類的(抽象)產品
抽象工廠模式 技術分享圖片
from abc import abstractmethod, ABCMeta


# ------抽象產品------

class PhoneShell(metaclass=ABCMeta):
    @abstractmethod
    def show_shell(self):
        pass


class CPU(metaclass=ABCMeta):
    @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()

    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()
示例代碼

技術分享圖片
內容:保證一個類只有一個實例,並提供一個訪問它的全局訪問點。
角色:
單例(Singleton)
適用場景
當類只能有一個實例而且客戶可以從一個眾所周知的訪問點訪問它時
優點:
對唯一實例的受控訪問
單例相當於全局變量,但防止了命名空間被汙染
與單例模式功能相似的概念:全局變量、靜態變量(方法)
單例模式 技術分享圖片
from abc import abstractmethod, ABCMeta

class Singleton(object):
    def __new__(cls, *args, **kwargs):
        if not hasattr(cls, "_instance"):
            cls._instance = super(Singleton, cls).__new__(cls)
        return cls._instance


class MyClass(Singleton):
    def __init__(self, name=None):
        if name is not None:
            self.name = name


a = MyClass("a")

print(a)
print(a.name)

b = MyClass("b")

print(b)
print(b.name)

print(a)
print(a.name)
示例代碼

算法3-設計模式