設(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()