結構型模式
適配器模式
內容:將一個類的接口轉換成客戶希望的另一個接口。適配器模式使
得原本由于接口不兼容而不能一起工作的那些類可以一起工作。
兩種實現方式:
類適配器:使用多繼承
對象適配器:使用組合
角色:
目標接口(Target)
待適配的類(Adaptee)
適配器(Adapter)
適用場景:
想使用一個已經存在的類,而它的接口不符合你的要求(對象適配器)想使用一些已經存在的子類,但不可能對每一個都進行子類化以匹配它們的接口。對象適配器可以適配它的父類接口。
from abc import ABCMeta, abstractmethodclass Payment(metaclass=ABCMeta):# abstract class@abstractmethoddef pay(self, money):passclass Alipay(Payment):def pay(self, money):print("支付寶支付%d元." % money)class WechatPay(Payment):def pay(self, money):print("微信支付%d元." % money)class BankPay:def cost(self, money):print("銀聯支付%d元." % money)class ApplePay:def cost(self, money):print("蘋果支付%d元." % money)# # 類適配器
# class NewBankPay(Payment, BankPay):
# def pay(self, money):
# self.cost(money)# 把不兼容的轉成兼容的
# 當有多個接口不同的類時,這樣會導致要寫多個類去繼承# 對象適配器
class PaymentAdapter(Payment):def __init__(self, payment):self.payment = paymentdef pay(self, money):self.payment.cost(money) # 調用不兼容對象的方法 , 包裝 不兼容的接口方法 成兼容的p = PaymentAdapter(BankPay()) # 一個類里放另一個類對象
p.pay(100)# 組合# class A:
# pass
#
# class B:
# def __init__(self):
# self.a = A()
橋模式
內容:
將一個事物的兩個維度分離,使其都可以獨立地變化。
角色:
抽象(Abstraction)
細化抽象(RefinedAbstraction)
實現者(Implementor)
具體實現者(ConcreteImplementor)
應用場景:
當事物有兩個維度上的表現,兩個維度都可能擴展時。
優點:
抽象和實現相分離
優秀的擴展能力
from abc import ABCMeta, abstractmethodclass Shape(metaclass=ABCMeta):def __init__(self, color):self.color = color@abstractmethoddef draw(self):passclass Color(metaclass=ABCMeta):@abstractmethoddef paint(self, shape):passclass Rectangle(Shape):name = "長方形"def draw(self):# 長方形邏輯self.color.paint(self)class Circle(Shape):name = "圓形"def draw(self):# 圓形邏輯self.color.paint(self) # 調用color 對象的paint并把self形狀對象傳過去,方便color的paint打印class Line(Shape):name = "直線"def draw(self):# 直線邏輯self.color.paint(self)class Red(Color):def paint(self, shape):print("紅色的%s" % shape.name)class Green(Color):def paint(self, shape):print("綠色的%s" % shape.name)class Blue(Color):def paint(self, shape):print("藍色的%s" % shape.name)shape = Line(Blue())
shape.draw()shape2 = Circle(Green()) # 先把color對象傳過來,以便draw調用# (其實draw調用的時候,是調用color的paint方法,并把shape對象傳給paint讓它去調用shape的name)
shape2.draw()# 兩個維度都可以擴展
組合模式?
內容:將對象組合成樹形結構以表示“部分-整體”的層次結構。組合模式使得用戶對單個對象和組合對象的使用具有一致性。
角色:
抽象組件(Component)
葉子組件(Leaf)
復合組件(Composite)
客戶端(Client)
from abc import ABCMeta, abstractmethod# 抽象組件
class Graphic(metaclass=ABCMeta):@abstractmethoddef draw(self):pass# 葉子組件
class Point(Graphic):def __init__(self, x, y):self.x = xself.y = ydef __str__(self):return "點(%s, %s)" % (self.x, self.y)def draw(self):print(str(self))# 葉子組件
class Line(Graphic):def __init__(self, p1, p2):self.p1 = p1self.p2 = p2def __str__(self):return "線段[%s, %s]" % (self.p1, self.p2)def draw(self):print(str(self))# 復合組件
class Picture(Graphic): # 組合(組裝類)def __init__(self, iterable):self.children = []for g in iterable:self.add(g)def add(self, graphic):self.children.append(graphic)def draw(self):print("------復合圖形------")for g in self.children:g.draw()print("------復合圖形------")p1 = Point(2,3)
l1 = Line(Point(3,4), Point(6,7)) # 將簡單的類對象,作為參數傳遞進行組合
l2 = Line(Point(1,5), Point(2,8))
pic1 = Picture([p1, l1, l2])p2 = Point(4,4)
l3 = Line(Point(1,1), Point(0,0))
pic2 = Picture([p2, l3])pic = Picture([pic1, pic2])
pic.draw()"""
------復合圖形------
------復合圖形------
點(2, 3)
線段[點(3, 4), 點(6, 7)]
線段[點(1, 5), 點(2, 8)]
------復合圖形------
------復合圖形------
點(4, 4)
線段[點(1, 1), 點(0, 0)]
------復合圖形------
------復合圖形------
"""
適用場景:
表示對象的“部分-整體”層次結構(特別是結構是遞歸的)
希望用戶忽略組合對象與單個對象的不同,用戶統一地使用組合結構中的所有對象
優點:
定義了包含基本對象和組合對象的類層次結構
簡化客戶端代碼,即客戶端可以一致地使用組合對象和單個對象
更容易增加新類型的組件
外觀模式
內容:為子系統中的一組接口提供一個一致的界面,外觀模式定義了一個高層接口,這個接口使得這一子系統更加容易使用。
角色:
外觀(facade)
子系統類(subsystem classes)
class CPU:def run(self):print("CPU開始運行")def stop(self):print("CPU停止運行")class Disk:def run(self):print("硬盤開始工作")def stop(self):print("硬盤停止工作")class Memory:def run(self):print("內存通電")def stop(self):print("內存斷電")class Computer: # Facadedef __init__(self):self.cpu = CPU()self.disk = Disk()self.memory = Memory()def run(self):self.cpu.run()self.disk.run()self.memory.run()def stop(self):self.cpu.stop()self.disk.stop()self.memory.stop()computer = Computer() # 高級別的封裝調用,使外觀調用一致
computer.run()
computer.stop()
優點:
減少系統相互依賴
提高了靈活性
提高了安全性
代理模式
內容:為其他對象提供一種代理以控制對這個對象的訪問。
應用場景:
遠程代理:為遠程的對象提供代理
虛代理:根據需要創建很大的對象
保護代理:控制對原始對象的訪問,用于對象有不同訪問權限時
from abc import ABCMeta, abstractmethodclass Subject(metaclass=ABCMeta):@abstractmethoddef get_content(self):pass@abstractmethoddef set_content(self, content):passclass RealSubject(Subject):def __init__(self, filename):self.filename = filenamewith open(filename, 'r', encoding='utf-8') as f:print("讀取文件內容")self.content = f.read()def get_content(self):return self.contentdef set_content(self, content):with open(self.filename, 'w', encoding='utf-8') as f:f.write(content)class VirtualProxy(Subject):def __init__(self, filename): # 不直接調用文件,防止文件過大,占到內存到self.filename = filename # 創建對象時不會讀取文件內容,self.subj = Nonedef get_content(self):if not self.subj:self.subj = RealSubject(self.filename) # 在調用get_content 時才真正去打開文件return self.subj.get_content()def set_content(self, content):if not subj:self.subj = RealSubject(self.filename)return self.subj.set_content(content)class ProtectedProxy(Subject): # 保護代理def __init__(self, filename):self.subj = RealSubject(filename)def get_content(self):return self.subj.get_content()def set_content(self, content):raise PermissionError("無寫入權限")#subj = RealSubject("test.txt")
#subj.get_content()subj = ProtectedProxy("test.txt")
print(subj.get_content())
# subj.set_content("abc")
角色:
抽象實體(Subject)
實體(RealSubject)
代理(Proxy)
優點:
遠程代理:可以隱藏對象位于遠程地址空間的事實
虛代理:可以進行優化,例如根據要求創建對象
保護代理:允許在訪問一個對象時有一些附加的內務處理
總結
以上是生活随笔為你收集整理的sjms-3 结构型模式的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。