Python設(shè)計(jì)模式-讀書筆記

設(shè)計(jì)模式

面向?qū)ο?/h2>

對(duì)象

封裝

多態(tài)

繼承

抽象

組合

設(shè)計(jì)規(guī)則

不良設(shè)計(jì)主要表現(xiàn)在4個(gè)方面

  • 不動(dòng)性:以這種方式開發(fā)的應(yīng)用程序非常難以重用舱禽。
  • 剛性:以這種方式開發(fā)的應(yīng)用程序,任何小的修改都會(huì)導(dǎo)致軟件的太多部分必須進(jìn)行相應(yīng)的改動(dòng)恩沽,所謂“牽一發(fā)而動(dòng)全身”誊稚。
  • 脆弱性:當(dāng)前應(yīng)用程序的任何更改都會(huì)導(dǎo)致現(xiàn)有系統(tǒng)變得非常容易崩潰。
  • 粘滯性:由于架構(gòu)層面的修改非常困難罗心,因此修改必須由開發(fā)人員在代碼或環(huán)境本身中進(jìn)行里伯。

創(chuàng)建型模式

單例模式

1、概念

  • 確保類有且只有一個(gè)對(duì)象被創(chuàng)建
  • 為對(duì)象提供一個(gè)訪問點(diǎn)协屡,以使程序可以全局訪問該對(duì)象
  • 控制共享資源的并行訪問
  • 所有的模塊都是單例

2俏脊、基本實(shí)現(xiàn)

class Singleton(object):
    def __new__(cls):
        if not hasattr(cls, 'instance'):
            cls.instance = super(Singleton, cls).__new__(cls)
        return cls.instance

s_1 = Singleton()
s_2 = Singleton()

print("objected created", s_1)
print("objected created", s_2)

# objected created <__main__.Singleton object at 0x00000137A8ADFF10>
# objected created <__main__.Singleton object at 0x00000137A8ADFF10>

3、懶漢式實(shí)例化

# 懶漢式實(shí)例化
class Singleton:
    __instance = None
    def __init__(self) -> None:
        if not Singleton.__instance:
            print("__init__ method called..")
        else:
            print("Instance already created:", self.getInstance())
    
    @classmethod
    def getInstance(cls):
        if not cls.__instance:
            cls.__instance = Singleton()
        return cls.__instance

# class initialized, but object not created
s = Singleton()
print("object created", Singleton.getInstance()) #Objcet gets created here

s1 = Singleton() # instance already created


'''
__init__ method called..
__init__ method called..
object created <__main__.Singleton object at 0x00000186165D2190>
Instance already created: <__main__.Singleton object at 0x00000186165D2190>
'''

4肤晓、Monostated單例模式

通常程序員需要的是讓實(shí)例共享相同的狀態(tài)爷贫,而不是同一性

本質(zhì)是用類變量替換了__dict__

class Borg:
    __shared_state = {}
    def __init__(self) -> None:
        self.x = 1
        self.__dict__ = self.__shared_state

B1 = Borg()
B2 = Borg()
B1.x = 100
print("Borg B1:", B1)
print("Borg B2:", B2)
print("object state B1:", B1.__dict__)
print("object state B2:", B2.__dict__)

"""
Borg B1: <__main__.Borg object at 0x000002E1E7DE4220>
Borg B2: <__main__.Borg object at 0x000002E1E7DE4250>
object state B1: {'x': 100}
object state B2: {'x': 100}
"""

# 使用__new__方法來實(shí)現(xiàn)Borg
class Borg2:
    _shared_state = {}
    def __new__(cls, *args, **kwargs) -> Any:
        obj = super(Borg2, cls).__new__(cls, *args, **kwargs)
        obj.__dict__ = cls._shared_state
        return obj

5、通過元類實(shí)現(xiàn)單例

# 元組
class MetaSingleton(type):
    _instances = {}
    def __call__(cls, *args, **kwds):
        if cls not in cls._instances:
            cls._instances[cls] = super(MetaSingleton, cls).__call__(*args, **kwds)
        return cls._instances[cls]

class Logger(metaclass=MetaSingleton):
    pass

logger1 = Logger()
logger2 = Logger()
print(logger1)
print(logger2)

"""
<__main__.Logger object at 0x000001A48982A5B0>
<__main__.Logger object at 0x000001A48982A5B0>
"""

6补憾、 demo1

import sqlite3

class MetaSingleton(type):
    _instances = {}
    def __call__(cls, *args, **kwargs):
        if cls not in cls._instances:
            cls._instances[cls] = super(MetaSingleton, cls).__call__(*args, **kwargs)
        return cls._instances[cls]


class Database(metaclass=MetaSingleton):
    connection = None
    def connect(self):
        if self.connection is None:
            self.connection = sqlite3.connect("db.sqlite3")
            self.cursorobj = self.connection.cursor()
        return self.cursorobj

db1 = Database().connect()
db2 = Database().connect()

print("db1:", db1)
print("db2:", db2)

demo2

class HealthCheck:
    _instance = None
    def __new__(cls, *args, **kwargs):  
        if not HealthCheck._instance:
            HealthCheck._instance = super(HealthCheck, cls).__new__(cls, *args, **kwargs)
        return HealthCheck._instance
    

    def __init__(self) -> None:
        self._servers = []
    
    def addServer(self):
        self._servers.append("Server 1")
        self._servers.append("Server 2")
        self._servers.append("Server 3")
        self._servers.append("Server 4")
    
    def changeServer(self):
        self._servers.pop()
        self._servers.append("Server 5")

hc1 = HealthCheck()
hc2 = HealthCheck()

hc1.addServer()
print("schedule health check for servers (1)...")
for i in range(4):
    print("checking", hc1._servers[i])

hc2.changeServer()
print("schedule health check for servers (2)...")
for i in range(4):
    print("checking", hc2._servers[i])

7漫萄、缺點(diǎn)

  • 全局變量可能在某處已經(jīng)被誤改,但是開發(fā)人員仍然認(rèn)為它們沒有發(fā)生變化盈匾,而該變量還在應(yīng)用程序的其他位置被使用腾务。
  • 可能會(huì)對(duì)同一對(duì)象創(chuàng)建多個(gè)引用。由于單例只創(chuàng)建一個(gè)對(duì)象削饵,因此這種情況下會(huì)對(duì)同一個(gè)對(duì)象創(chuàng)建多個(gè)引用岩瘦。
  • 所有依賴于全局變量的類都會(huì)由于一個(gè)類的改變而緊密耦合為全局?jǐn)?shù)據(jù),從而可能在無意中影響另一個(gè)類窿撬。

工廠模式

1启昧、“工廠”——一個(gè)負(fù)責(zé)創(chuàng)建其他類型對(duì)象的類

2、優(yōu)點(diǎn)

  • 松耦合劈伴,即對(duì)象的創(chuàng)建可以獨(dú)立于類的實(shí)現(xiàn)
  • 客戶端無需了解創(chuàng)建對(duì)象的類密末,但是照樣可以使用它來創(chuàng)建對(duì)象。它只需要知道需要傳遞的接口跛璧、方法和參數(shù)严里,就能夠創(chuàng)建所需類型的對(duì)象了。這簡化了客戶端的實(shí)現(xiàn)
  • 可以輕松地在工廠中添加其他類來創(chuàng)建其他類型的對(duì)象追城,而這無需更改客戶端代碼刹碾。最簡單的情況下,客戶端只需要傳遞另一個(gè)參數(shù)就可以了
  • 工廠還可以重用現(xiàn)有對(duì)象座柱。但是教硫,如果客戶端直接創(chuàng)建對(duì)象的話叨吮,總是創(chuàng)建一個(gè)新對(duì)象

3、3種變體

  • 簡單工廠模式
    • 允許接口創(chuàng)建對(duì)象瞬矩,但不會(huì)暴露對(duì)象的創(chuàng)建邏輯
  • 工廠方法模式
    • 允許接口創(chuàng)建對(duì)象茶鉴,但使用哪個(gè)類來創(chuàng)建對(duì)象,則是交由子類決定的
from abc import ABC, ABCMeta, abstractmethod


class Section(metaclass=ABCMeta):
    @abstractmethod
    def describe(self):
        psdd


class PersonScetion(Section):
    def describe(self):
        print("Personal Section")


class AlbumSection(Section):
    def describe(self):
        print("album Section")


class PatentSection(Section):
    def describe(self):
        print("Patent Section")


class PublicationSection(Section):
    def describe(self):
        print("Publication Section")


class Profile(metaclass=ABCMeta):
    def __init__(self):
        self.sections = []
        self.createProfile()
    
    @abstractmethod
    def createProfile(self):
        pass

    def getSections(self):
        return self.sections
    
    def addSections(self, section):
        self.sections.append(section)

class linkedin(Profile):
    def createProfile(self):
        self.addSections(PersonScetion())
        self.addSections(PatentSection())
        self.addSections(PublicationSection())


class facebook(Profile):
    def createProfile(self):
        self.sections.append(PersonScetion())
        self.sections.append(AlbumSection())


if __name__ == "__main__":
    profile_type= input("[LinkedIn or FaceBook]?")
    profile = eval(profile_type.lower())()
    print("creating profole..", type(profile).__name__)
    print("Profile has sections -- ", profile.getSections())+-
  • 抽象工廠模式
    • 抽象工廠是一個(gè)能夠創(chuàng)建一系列相關(guān)的對(duì)象而無需指定/公開其具體類的接口景用。該模式能夠提供其他工廠的對(duì)象涵叮,在其內(nèi)部創(chuàng)建其他對(duì)象。
from abc import ABCMeta, abstractmethod


class PizzaFactory(metaclass=ABCMeta):

    @abstractmethod
    def cretaeVegPizza(self):
        pass

    @abstractmethod
    def creatNonVegPizza(self):
        pass


class IndiaPizzaFactory(PizzaFactory):
    def cretaeVegPizza(self):
        return DeluxVeggiePizza()
    
    def creatNonVegPizza(self):
        return ChickenPizza()
    

class USPizzaFactory(PizzaFactory):
    def cretaeVegPizza(self):
        return MexicanVegPizza()
    
    def creatNonVegPizza(self):
        return HamPizza()


class VegPizza(metaclass=ABCMeta):
    @abstractmethod
    def prepare(self, VegPizza):
        pass


class NonVegPizza(metaclass=ABCMeta):
    @abstractmethod
    def serve(self, VegPizza):
        pass


class DeluxVeggiePizza(VegPizza):
    def prepare(self):
        print("prepare", type(self).__name__)


class ChickenPizza(NonVegPizza):
    def serve(self, VegPizza):
        print(type(self).__name__, "is served with Chicken on ", type(VegPizza).__name__)


class MexicanVegPizza(VegPizza):
    def prepare(self):
        print("Prepare", type(self).__name__)

class HamPizza(NonVegPizza):
    def serve(self, VegPizza):
        print(type(self).__name__, "is served with Chicken on ", type(VegPizza).__name__)
        

class PizzaStore:
    def __init__(self) -> None:
        pass

    def makePizzas(self):
        for factory in [IndiaPizzaFactory(), USPizzaFactory()]:
            self.factory = factory
            self.NonVegPizza = self.factory.creatNonVegPizza()
            self.vegPizza = self.factory.cretaeVegPizza()
            self.vegPizza.prepare()
            self.NonVegPizza.serve(self.vegPizza)

abcdd = USPizzaFactory()
pizza = PizzaStore()
pizza.makePizzas()

結(jié)構(gòu)型設(shè)計(jì)模式

1伞插、結(jié)構(gòu)型設(shè)計(jì)模式

  • 結(jié)構(gòu)型模式描述如何將對(duì)象和類組合成更大的結(jié)構(gòu)割粮。
  • 結(jié)構(gòu)型模式是一種能夠簡化設(shè)計(jì)工作的模式,因?yàn)樗軌蛘页龈唵蔚姆椒▉碚J(rèn)識(shí)或表示實(shí)體之間的關(guān)系媚污。在面向?qū)ο笫澜缰幸ㄆ埃瑢?shí)體指的是對(duì)象或類。
  • 類模式可以通過繼承來描述抽象耗美,從而提供更有用的程序接口京髓,而對(duì)象模式則描述了如何將對(duì)象聯(lián)系起來從而組合成更大的對(duì)象。結(jié)構(gòu)型模式是類和對(duì)象模式的綜合體商架。

門面設(shè)計(jì)模式

完成了下列事項(xiàng):

  • 它為子系統(tǒng)中的一組接口提供一個(gè)統(tǒng)一的接口堰怨,并定義一個(gè)高級(jí)接口來幫助客戶端通過更加簡單的方式使用子系統(tǒng)
  • 門面所解決問題是,如何用單個(gè)接口對(duì)象來表示復(fù)雜的子系統(tǒng)蛇摸。實(shí)際上备图,它并不是封裝子系統(tǒng),而是對(duì)底層子系統(tǒng)進(jìn)行組合
  • 它促進(jìn)了實(shí)現(xiàn)與多個(gè)客戶端的解耦

這個(gè)模式有3個(gè)主要的參與者:

  • 門面:門面的主要責(zé)任是赶袄,將一組復(fù)雜導(dǎo)致系統(tǒng)封裝起來揽涮,從而為外部世界提供一個(gè)舒適的外觀。
  • 系統(tǒng):這代表一組不同的子系統(tǒng)饿肺,使整個(gè)系統(tǒng)混雜在一起蒋困,難以觀察或使用
  • 客戶端:客戶端與門面進(jìn)行交互,這樣就可以輕松地與子系統(tǒng)進(jìn)行通信并完成工作了唬格。不必?fù)?dān)心系統(tǒng)的復(fù)雜性。
"""
門面設(shè)計(jì)模式

門面類 EventManager
"""

class EventManager:
    
    def __init(self):
        print("Event Manager:: Let me talk to the folfs \n")

    def arrange(self):
        self.hotelier = Hotelier()
        self.hotelier.bookHotel()

        self.florist = Florist()
        self.florist.setFlowerRequirements()

        self.caterer = Caterer()
        self.caterer.setCuisine()

        self.musician = Musician()
        self.musician.setMusicType()


class Hotelier:
    def __init__(self):
        print("Arranging the Hotel for Marriage? --")

    def __isAvailable(self):
        print("Is the Hotel free for the event on given date?")
        return True
    
    def bookHotel(self):
        if self.__isAvailable():
            print("Registered the booking \n \n")
        

class Florist:
    def __init__(self):
        print("Flower Decorations for the Events? --")

    def setFlowerRequirements(self):
        print("Carnations, Roses and lilies would be used for Decorations \n\n")
    

class Caterer:
    def __init__(self):
        print("Food Arrangements for the Event --")
    
    def setCuisine(self):
        print("Chinese & Continental Cuisine to be served \n\n")
    

class Musician:
    def __init__(self) -> None:
        print("Musical Arrangements for the Marriage --")
    
    def setMusicType(self):
        print("Jazz and Classical will be played\n\n")


class You:
    def __init__(self) -> None:
        print("You:: Whos! Marriage Arrangements??!!!")
    
    def askEventManager(self):
        print("You:: Let's Contact the Event Manager \n\n")
        em = EventManager()
        em.arrange()
    
    def __del__(self):
        print("You:: Thanks to Event Manager, all prearations done!")
    
you = You()
you.askEventManager()

代理模式

在設(shè)計(jì)模式的上下文中颜说,代理是充當(dāng)實(shí)際對(duì)象接口的類购岗。

代理就是封裝實(shí)際服務(wù)對(duì)象的包裝器或代理人。

代理可以為其包裝的對(duì)象提供附加功能门粪,而無需更改對(duì)象的代碼喊积。

代理模式的主要目的是為其他對(duì)象提供一個(gè)代理者或占位符,從而控制對(duì)實(shí)際對(duì)象的訪問玄妈。

代理模式可以用于多種場景:

  • 它能夠以更簡單的方式表示一個(gè)復(fù)雜的系統(tǒng)乾吻。例如髓梅,涉及多個(gè)復(fù)雜計(jì)算或過程的系統(tǒng)應(yīng)該提供一個(gè)更簡單的接口,讓它充當(dāng)客戶端的代理绎签。
  • 它提高了現(xiàn)有的實(shí)際對(duì)象的安全性枯饿。在許多情況下,都不允許客戶端直接訪問實(shí)際對(duì)象诡必。這是因?yàn)閷?shí)際對(duì)象可能受到惡意活動(dòng)的危害奢方。這時(shí)候,代理就能起到抵御惡意活動(dòng)的盾牌作用爸舒,從而保護(hù)了實(shí)際的對(duì)象蟋字。
  • 它為不同服務(wù)器上的遠(yuǎn)程對(duì)象提供本地接口。一個(gè)明顯的例子是客戶端希望在遠(yuǎn)程系統(tǒng)上運(yùn)行某些命令的分布式系統(tǒng)扭勉,但客戶端可能沒有直接的權(quán)限來實(shí)現(xiàn)這一點(diǎn)鹊奖。
  • 它為消耗大量內(nèi)存的對(duì)象提供了一個(gè)輕量級(jí)的句柄。有時(shí)涂炎,你可能不想加載主要對(duì)象忠聚,除非它們真的有必要。
"""
代理
"""

from typing import AsyncGenerator


class Actor:
    def __init__(self) -> None:
        self.is_busy = False
    
    def occuiped(self):
        self.is_busy = True
        print(type(self).__name__, "is occuiped with current movie")
    
    def available(self):
        self.is_busy = False
        print(type(self).__name__, "is free for the movie")
    
    def getStatus(self):
        return self.is_busy
    

class Agent:
    def __init__(self) -> None:
        self.principal = None
        self.actor = Actor()
    
    def work(self):
        if self.actor.getStatus():
            self.actor.occuiped()
        else:
            self.actor.available()


if __name__ == "__main__":
    r = Agent()
    r.work()

代理模式有下述3個(gè)主要的參與者:

  • 代理:它維護(hù)一個(gè)引用璧尸,允許代理(Proxy)通過這個(gè)引用來訪問實(shí)際對(duì)象咒林。它提供了一個(gè)與主題(Subject)相同的接口,以便代理可以替換真實(shí)的主題爷光。代理還負(fù)責(zé)創(chuàng)建和刪除真實(shí)主題(RealSubject)垫竞。
  • 主題:它定義了RealSubject和Proxy的公共接口。以Proxy和RealSubject的形式實(shí)現(xiàn)主題(Subject)蛀序,使用RealSubject的任何地方都可以使用代理(Proxy)
  • 真實(shí)主題:它定義代理(Proxy)所代表的真實(shí)對(duì)象欢瞪。

從數(shù)據(jù)結(jié)構(gòu)的角度來看:

  • 代理:它是一個(gè)控制對(duì)RealSubject類訪問的類。它處理客戶端的請(qǐng)求徐裸,負(fù)責(zé)創(chuàng)建或刪除RealSubject遣鼓。
  • 主題/真實(shí)主題:主題是定義真實(shí)主題(RealSubject)和代理(Proxy)相類似的接口。RealSubject是Subject接口的實(shí)際實(shí)現(xiàn)重贺。它提供了真正的功能骑祟,然后由客戶端使用。
  • 客戶端:它訪問要完成工作的Proxy類气笙。Proxy類在內(nèi)部控制對(duì)RealSubject的訪問次企,并引導(dǎo)客戶端(Client)所請(qǐng)求的工作。

根據(jù)代理的使用方式潜圃,我們可以將它們分為虛擬代理缸棵、遠(yuǎn)程代理、保護(hù)代理和智能代理谭期。

虛擬代理

如果一個(gè)對(duì)象實(shí)例化后會(huì)占用大量內(nèi)存的話堵第,可以先利用占位符來表示吧凉,這就是所謂的虛擬代理。

遠(yuǎn)程代理

它給位于遠(yuǎn)程服務(wù)器或不同地址空間上的實(shí)際對(duì)象提供了一個(gè)本地表示

保護(hù)代理

這種代理能夠控制RealSubject的敏感對(duì)象的訪問踏志。

智能代理

智能代理在訪問對(duì)象時(shí)插入其他操作阀捅。

from abc import ABCMeta, abstractmethod

class Payment(metaclass=ABCMeta):

    @abstractmethod
    def do_pay(self):
        pass


class Bank(Payment):
    def __init__(self) -> None:
        self.card = None
        self.account = None

    def __getAccount(self):
        self.account = self.card
        return self.account
    
    def __hasFunds(self):
        print("Bank:: Checking if Account", self.__getAccount(), "has enough funds")
        return True
    
    def setCard(self, card):
        self.card = card
    
    def do_pay(self):
        if self.__hasFunds():
            print("Bank:: Paying the merchant")
            return True
        else:
            print("Bank:: Sorry, not enough funds!")
            return False


class DebitCard(Payment):
    def __init__(self) -> None:
        self.bank = Bank()
    
    def do_pay(self):
        card = input("Proxy:: Punch in Card Number")
        self.bank.setCard(card)
        return self.bank.do_pay


class You:
    def __init__(self) -> None:
        print("You:: Lets buy the Denim shirt")
        self.debitCard = DebitCard()
        self.isPurchased = None
    
    def make_payment(self):
        self.isPurchased = self.debitCard.do_pay()
    
    def __del__(self):
        if self.isPurchased:
            print("You:: Wow! Denim shirt is Mine")
        else:
            print("You:: I should earn more:")


if __name__ == "__main__":
    you = You()
    you.make_payment()

代理模式的優(yōu)點(diǎn):

  • 代理可以通過緩存笨重的對(duì)象或頻繁訪問的對(duì)象來提高應(yīng)用程序的性能
  • 代理還提供對(duì)于真實(shí)主題的訪問授權(quán)。因此狰贯,只有提供合適權(quán)限的情況下也搓,這個(gè)模式才會(huì)接受委派。
  • 遠(yuǎn)程代理還便于與可用作網(wǎng)絡(luò)連接和數(shù)據(jù)庫連接的遠(yuǎn)程服務(wù)器進(jìn)行交互涵紊,并可用于監(jiān)視系統(tǒng)傍妒。

行為型模式

觀察者模式

觀察者模式的主要目標(biāo):

  • 它定義了對(duì)象之間的一對(duì)多的依賴關(guān)系,從而使得一個(gè)對(duì)象中的任何更改都將自動(dòng)通知給其他依賴對(duì)象摸柄;
  • 它封裝了主題的核心組件颤练。

觀察者模式工作場景:

  • 在分布式系統(tǒng)中實(shí)現(xiàn)事件服務(wù)
  • 用作新聞機(jī)構(gòu)的框架
  • 股票市場
from abc import ABCMeta, abstractmethod
from typing import Any


class NewsPublisher:

    def __init__(self):
        self.__subscribers = []
        self.__latest_news = None
    
    def attach(self, subscriber):
        self.__subscribers.append(subscriber)
    
    def detach(self):
        return self.__subscribers.pop()

    def subscribers(self):
        return [type(sub).__name__ for sub in self.__subscribers]

    def notify_subscribers(self):
        for sub in self.__subscribers:
            sub.update()
    
    def add_news(self, news):
        self.__latest_news = news

    def getNews(self):
        return 'Got News:', self.__latest_news
    

class Subscriber(metaclass=ABCMeta):
    
    @abstractmethod
    def update(self):
        pass


class SMSSubscriber:

    def __init__(self, publisher) -> None:
        self.publisher = publisher
        self.publisher.attach(self)

    def update(self):
        print(type(self).__name__, self.publisher.getNews())
    

class EmailSubscriber:
    
    def __init__(self, publisher) -> None:
        self.publisher = publisher
        self.publisher.attach(self)
    
    def update(self):
        print(type(self).__name__, self.publisher.getNews())
        

class AnyOtherSubscriber:

    def __init__(self, publisher):
        self.publisher = publisher
        self.publisher.attach(self)
    
    def update(self):
        print(type(self).__name__, self.publisher.getNews())
    


if __name__ == '__main__':
    news_publisher = NewsPublisher()
    for subscriber in [SMSSubscriber, EmailSubscriber, AnyOtherSubscriber]:
        subscriber(news_publisher)
        
    print(news_publisher.subscribers)

    news_publisher.add_news("hello world")
    news_publisher.notify_subscribers()

    print("\n Detached:", type(news_publisher.detach()).__name__)
    print("\nSubscribers:", news_publisher.subscribers())
    news_publisher.add_news("second news")
    news_publisher.notify_subscribers()

命令設(shè)計(jì)模式

命令模式優(yōu)點(diǎn):

  • 將調(diào)用操作的類與知道如何執(zhí)行該操作的對(duì)象解耦
  • 提供隊(duì)列系統(tǒng)后,可以創(chuàng)建一系列命令
  • 添加新命令更加容易驱负,并且無需更改現(xiàn)有代碼
  • 使用命令模式來定義回滾系統(tǒng)
from abc import ABC, ABCMeta, abstractmethod

class Command(metaclass=ABCMeta):
    
    def __init__(self, recv):
        self.recv = recv
    
    @abstractmethod
    def execute(self):
        pass


class ConcreteCommand(Command):

    def __init__(self, recv):
        self.recv = recv
    
    def execute(self):
        self.recv.action()
    

class Receiver:
    def action(self):
        print("Receiver Action")
    

class Invoker:
    def command(self, cmd):
        self.cmd = cmd
    
    def execute(self):
        self.cmd.execute()
    

if __name__ = '__main__':
    recv = Receiver()
    cmd = ConcreteCommand(recv)
    invoker = Invoker()
    invoker.command(cmd)
    invoker.execute()
from abc import ABCMeta, abstractmethod


class Order(metaclass=ABCMeta):

    @abstractmethod
    def execute(self):
        pass


class BuyStockOrder(Order):

    def __init__(self, stock):
        self.stock = stock
    
    def execute(self):
        self.stock.buy()
    

class SellStockOrder(Order):

    def __init__(self, stock):
        self.stock = stock
    
    def execute(self):
        self.stock.sell()


class StockTrade:

    def buy(self):
        print("you will buy stocks")
    
    def sell(self):
        print("you will sell stocks")
    

class Agent:
    def __init__(self):
        self.__orderQueue = []

    def placeOrder(self, order):
        self.__orderQueue.append(order)
        order.execute()


if __name__ == '__main__':
    # Client
    stock = StockTrade()
    buyStock = BuyStockOrder(stock)
    sellStock = SellStockOrder(stock)

    # Invoker
    agent = Agent()
    agent.placeOrder(buyStock)
    agent.placeOrder(sellStock)

模板設(shè)計(jì)模式

模板方法模式象適用場景:

  • 當(dāng)多個(gè)算法或類實(shí)現(xiàn)類似或相同邏輯的時(shí)候嗦玖;
  • 在子類中實(shí)現(xiàn)算法有助于減少重復(fù)代碼的時(shí)候
  • 可以讓子類利用覆蓋實(shí)現(xiàn)行為來定義多個(gè)算法的時(shí)候

模板方法模式的優(yōu)點(diǎn):

  • 沒有代碼重復(fù)
  • 由于模板方法模式使用繼承而不是合成,因此能夠?qū)Υa進(jìn)行重用跃脊。所以宇挫,只有為數(shù)不多的幾個(gè)方法需要重寫
  • 靈活性允許子類決定如何實(shí)現(xiàn)算法中的步驟。
from abc import ABCMeta, abstractmethod


class Trip(metaclass=ABCMeta):

    @abstractmethod
    def setTransport(self):
        pass

    @abstractmethod
    def day1(self):
        pass

    @abstractmethod
    def day2(self):
        pass

    @abstractmethod
    def day3(self):
        pass

    @abstractmethod
    def returnHome(self):
        pass

    def itinerary(self):
        self.setTransport()
        self.day1()
        self.day2()
        self.day3()
        self.returnHome()

    
class VeniceTrip(Trip):
    
    def setTransport(self):
        print("take a boat and find your way in the Grand Canal")
    
    def day1(self):
        print("day1,Venice vist...")
    
    def day2(self):
        print("day2,Venice vist...")
    
    def day3(self):
        print("day3,Venice vist...")
    
    def returnHome(self):
        print("Venice go home")


class MaldiversTrip(Trip):
    
    def setTransport(self):
        print("on foot...")
    
    def day1(self):
        print("day1,Maldivers vist...")
    
    def day2(self):
        print("day2,Maldivers vist...")
    
    def day3(self):
        print("day3,Maldivers vist...")
    
    def returnHome(self):
        print("Maldivers go home")


class TravelAgency:

    def __init__(self) -> None:
        self.trip = None

    def arrangeTrip(self):
        choice = input("Venice or Maldivers?")
        if choice == "Venice":
            self.trip = VeniceTrip()
            self.trip.itinerary()
        if choice == "Maldivers":
            self.trip = MaldiversTrip()
            self.trip.itinerary()


if __name__ == "__main__":
    customer = TravelAgency()
    customer.arrangeTrip()

狀態(tài)設(shè)計(jì)模式

狀態(tài)模式也可以看作是在運(yùn)行時(shí)改變對(duì)象行為的一種方式酪术。

狀態(tài)模式的優(yōu)點(diǎn):

  • 在狀態(tài)設(shè)計(jì)模式中器瘪,對(duì)象的行為是其狀態(tài)的函數(shù)結(jié)果,并且行為在運(yùn)行時(shí)根據(jù)狀態(tài)而改變
  • 使用狀態(tài)模式绘雁,實(shí)現(xiàn)多態(tài)行為的好處是顯而易見的橡疼,并且更易于添加狀態(tài)來支持額外的行為。
  • 狀態(tài)設(shè)計(jì)模式還提高了聚合性庐舟,因?yàn)樘囟ㄓ跔顟B(tài)的行為被聚合到ConcreteState類中欣除,并且放置在代碼中的同一個(gè)地方
  • 使用狀態(tài)設(shè)計(jì)模式,通過只添加一個(gè)ConcreteState類來添加行為是非常容易的挪略。因此历帚,狀態(tài)模式不僅改善了擴(kuò)展應(yīng)用程序行為時(shí)的靈活性,而且全面提高了代碼的可維護(hù)性杠娱。
from abc import abstractmethod, ABCMeta


class State(metaclass=ABCMeta):

    @abstractmethod
    def Handle(self):
        pass


class ConcreteStateB(State):
    def Handle(self):
        print("Concrete State B")
    

class ConcreteStateA(State):
    
    def Handle(self):
        print("Concrete State A")
    

class Context(State):
    
    def __init__(self):
        self.state = None
    
    def getState(self):
        return self.state
    
    def setState(self, state):
        self.state= state
    
    def Handle(self):
        self.state.Handle()


if __name__ == '__main__':
    context = Context()
    stateA = ConcreteStateA()
    stateB = ConcreteStateB()

    context.setState(stateA)
    context.Handle()

復(fù)合模式

復(fù)合模式將兩個(gè)或更多模式組合成解決常見或普遍性問題的解決方案挽牢。

MVC模式(模型-試圖-控制器模式)

MVC模式的工作機(jī)制:

  • 模型提供數(shù)據(jù)和業(yè)務(wù)邏輯
  • 視圖負(fù)責(zé)數(shù)據(jù)的展示
  • 控制器是兩者的粘合劑

MVC模式應(yīng)用場景:

  • 當(dāng)需要更改展示方式而不更改業(yè)務(wù)邏輯時(shí)
  • 多個(gè)控制器可用于使用多個(gè)視圖來更改用戶界面上的展示
  • 當(dāng)模型改變時(shí),視圖無需改動(dòng)

MVC模式的優(yōu)點(diǎn)

  • 有助于提高可維護(hù)性墨辛,強(qiáng)制松耦合卓研,并降低復(fù)雜性
  • MVC允許對(duì)前端進(jìn)行獨(dú)立更改趴俘,而對(duì)后端邏輯無需任何修改或只需進(jìn)行很少的更改睹簇,因此開發(fā)工作仍可以獨(dú)立運(yùn)行
  • 可以更改模型或業(yè)務(wù)邏輯奏赘,而無需對(duì)視圖進(jìn)行任何更改
  • 可以更改控制器,而不會(huì)對(duì)視圖或模型造成任何影響
class Model:
    services = {
        'emial': {"number": 1000, 'price': 2},
        'sms': {'number': 1000, 'price': 10},
        'voice': {'number': 1000, 'price': 15}
    }


class View:

    def list_services(self, services):
        for svc in services:
            print(svc, " ")
        
    def list_pricing(self, services):
        for svc in services:
            print('For', Model.services[svc]['number'], svc, 'message you pay $', Model.services[svc]['price'])

    
class Controller:
    
    def __init__(self) -> None:
        self.model = Model()
        self.view = View()

    def get_services(self):
        services = self.model.services.keys()
        return self.view.list_services(services)
    
    def get_pricing(self):
        services = self.model.services.keys()
        return self.view.list_pricing(services)



if __name__ == '__main__':
    controller = Controller()
    print("Services Provided:")
    controller.get_services()
    print("Pricing for Services:")
    controller.get_pricing()

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末太惠,一起剝皮案震驚了整個(gè)濱河市磨淌,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌凿渊,老刑警劉巖梁只,帶你破解...
    沈念sama閱讀 218,682評(píng)論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異埃脏,居然都是意外死亡搪锣,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,277評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門彩掐,熙熙樓的掌柜王于貴愁眉苦臉地迎上來构舟,“玉大人,你說我怎么就攤上這事堵幽」烦” “怎么了?”我有些...
    開封第一講書人閱讀 165,083評(píng)論 0 355
  • 文/不壞的土叔 我叫張陵朴下,是天一觀的道長努咐。 經(jīng)常有香客問我,道長殴胧,這世上最難降的妖魔是什么渗稍? 我笑而不...
    開封第一講書人閱讀 58,763評(píng)論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮溃肪,結(jié)果婚禮上免胃,老公的妹妹穿的比我還像新娘。我一直安慰自己惫撰,他們只是感情好羔沙,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,785評(píng)論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著厨钻,像睡著了一般扼雏。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上夯膀,一...
    開封第一講書人閱讀 51,624評(píng)論 1 305
  • 那天诗充,我揣著相機(jī)與錄音,去河邊找鬼诱建。 笑死蝴蜓,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播茎匠,決...
    沈念sama閱讀 40,358評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼格仲,長吁一口氣:“原來是場噩夢(mèng)啊……” “哼!你這毒婦竟也來了诵冒?” 一聲冷哼從身側(cè)響起凯肋,我...
    開封第一講書人閱讀 39,261評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎汽馋,沒想到半個(gè)月后侮东,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,722評(píng)論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡豹芯,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,900評(píng)論 3 336
  • 正文 我和宋清朗相戀三年悄雅,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片铁蹈。...
    茶點(diǎn)故事閱讀 40,030評(píng)論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡煤伟,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出木缝,到底是詐尸還是另有隱情便锨,我是刑警寧澤,帶...
    沈念sama閱讀 35,737評(píng)論 5 346
  • 正文 年R本政府宣布我碟,位于F島的核電站放案,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏矫俺。R本人自食惡果不足惜吱殉,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,360評(píng)論 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望厘托。 院中可真熱鬧友雳,春花似錦、人聲如沸铅匹。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,941評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽包斑。三九已至流礁,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間罗丰,已是汗流浹背神帅。 一陣腳步聲響...
    開封第一講書人閱讀 33,057評(píng)論 1 270
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留萌抵,地道東北人找御。 一個(gè)月前我還...
    沈念sama閱讀 48,237評(píng)論 3 371
  • 正文 我出身青樓元镀,卻偏偏與公主長得像,于是被迫代替她去往敵國和親霎桅。 傳聞我的和親對(duì)象是個(gè)殘疾皇子胸嘴,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,976評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容