1. 程式人生 > >設計模式二:結構型模式

設計模式二:結構型模式

ner 進行 turn 維度 sha 外觀 lena for efi


結構型模式(7)種:適配器模式,橋模式,組合模式,裝飾模式,外觀模式,享元模式,代理模式

1、適配器模式

內容:將一個類的接口轉換成客戶希望的另一個接口。適配器模式使得原本由於接口不兼容而不能一起工作的那些類可以一起工作。

兩種實現方式:

  • 類適配器:使用多繼承
  • 對象適配器:使用組合 

角色:

  1、目標接口(target)

  2、待適配的類(Adaptee)

  3、適配器(Adapter)

適用場景:

  想使用一個已經存在的類,而它的接口不符合你的要求

  (對象適配器)想使用一些已經存在的子類,但不可能對每一個都進行子類化以匹配它們的接口。對象適配器可以適配它的父類接口。

技術分享圖片
from abc import ABCMeta, abstractmethod


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


class 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 PaymentAdapter(Payment, BankPay): # def pay(self, money): # self.cost(money) # 對象適配器
class PaymentAdapter(Payment): def __init__(self, payment): self.payment = payment def pay(self, money): self.payment.cost(money) p = PaymentAdapter(BankPay()) p.pay(100) ## 目標接口:Payment 待適配的類:BankPay, ApplePay 適配器:PaymentAdapter
View Code

2、橋模式

內容:將一個事物的兩個維度分離,使其都可以獨立地變化。

角色:

  • 抽象(Abstraction)
  • 細化抽象(RefinedAbstraction)
  • 實現者(Implementor)
  • 具體實現者(ConcreteImplementor)

應用場景:當事物有兩個維度上的表現,兩個維度都有可能擴展時。

優點:

  • 抽象和實現相分離
  • 優秀的擴展能力
技術分享圖片
from abc import ABCMeta, abstractmethod

class Shape(metaclass=ABCMeta):
    def __init__(self, color):
        self.color = color

    @abstractmethod
    def draw(self):
        pass


class Color(metaclass=ABCMeta):
    @abstractmethod
    def paint(self, shape):
        pass


class Rectangle(Shape):
    name = "長方形"
    def draw(self):
        # 長方形邏輯
        self.color.paint(self)


class Circle(Shape):
    name = "圓形"
    def draw(self):
        # 圓形邏輯
        self.color.paint(self)


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())
shape2.draw()


##
    抽象:Shape
    細化抽象:Color
    實現者:Red,Green,Blue
    具體實現者:Rectangle,Circle, Line
View Code

3、組合模式

內容:將對象組合成樹型結構以表示"部分-整體"的層次結構。組合模式使得用戶對單個對象和組合對象的使用具有一致性。

角色:

  • 抽象組件(Component)
  • 葉子組件(Leaf)
  • 復合組件(Composite)
  • 客戶端(Client)

適用場景:

  表示對象的"部分-整體"層次結構(特別是結構是遞歸的)

  希望用戶忽略組合對象與單個對象的不同,用戶統一地適用組合結構中的所有對象。

優點:

  1. 定義了包含基本對象和組合對象的層次結構
  2. 簡化客戶端代碼,即客戶端可以一直地使用組合對象和單個對象
  3. 更容易增加新類型的組件
技術分享圖片
from abc import ABCMeta, abstractmethod


# 抽象組件
class Graphic(metaclass=ABCMeta):
    @abstractmethod
    def draw(self):
        pass


# 葉子組件
class Point(Graphic):
    def __init__(self, x, y):
        self.x = x
        self.y = y

    def __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 = p1
        self.p2 = p2

    def __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()
View Code

4、外觀模式

內容:為子系統中的一組接口提供一個一致的界面,外觀模式定義了一個高層接口,這個接口使得這一子系統更加容易使用。

角色:

  • 外觀(facade)
  • 子系統類(subsystem classes)

優點:

  1. 減少系統相互依賴
  2. 提高了靈活性
  3. 提高了安全性
技術分享圖片
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:
    def __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()
View Code

5、代理模式

內容:為其他對象提供一種代理以控制對這個對象的訪問。

應用場景:

  • 遠程代理:為遠程的對象提供代理
  • 虛代理:根據需要創建很大的對象
  • 保護代理:控制對原始對象的訪問,用於對象有不同訪問權限時

角色:

  抽象實體(Subject)

  實體(Realsubject)

  代理(Proxy)

優點:

  • 遠程代理:可以隱藏對象位於遠程地址空間的事實
  • 虛代理:可以進行優化,例如可以根據需求創建對象
  • 保護代理:允許在訪問一個對象時有一些附加的內務處理
技術分享圖片
from abc import ABCMeta, abstractmethod

class Subject(metaclass=ABCMeta):

    @abstractmethod
    def get_content(self):
        pass

    @abstractmethod
    def set_content(self, content):
        pass


class RealSubject(Subject):
    def __init__(self, filename):
        self.filename = filename
        f = open(filename, r, encoding="utf-8")
        print("讀取文件內容")
        self.content = f.read()
        f.close()

    def get_content(self):
        return self.content

    def set_content(self, content):
        f = open(self.filename, w, encoding="utf-8")
        f.write(content)
        f.close()


class VirtualProxy(Subject):
    def __init__(self, filename):
        self.filename = filename
        self.subj = None

    def get_content(self):
        if not self.subj:
            self.subj = RealSubject(self.filename)
        return self.subj.get_content()

    def set_content(self, content):
        if not self.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 = ProtectedProxy("test.txt")
print(subj.get_content())
subj.set_content("abc")
View Code

設計模式二:結構型模式