返回文章列表

Python 行為與架構設計模式解析

本文深入探討 Python 中的行為設計模式與架構設計模式,包含迭代器模式、範本方法模式、MVC 等,並提供程式碼範例說明如何在實際開發中應用這些模式,提升程式碼的可維護性和擴充套件性。

軟體設計 Python

軟體開發中,設計模式提供瞭解決常見設計問題的有效方案。本文聚焦於 Python 的行為設計模式和架構設計模式,包含迭代器模式、範本方法模式和 MVC 模式,並輔以程式碼範例,展示如何在實際開發中應用這些模式。迭代器模式提供一種依序存取聚合物件元素的方法,而範本方法模式則定義了演算法的骨架,允許子類別自訂特定步驟。MVC 模式則將應用程式分為模型、檢視和控制器,實作關注點分離,提升程式碼的可維護性和擴充套件性。

行為設計模式中的迭代器模式與範本方法模式

在軟體開發過程中,設計模式為我們提供了可重複使用的解決方案,以應對常見的軟體設計問題。本篇文章將探討兩種重要的行為設計模式:迭代器模式(Iterator Pattern)與範本方法模式(Template Method Pattern),並透過具體的Python範例來說明這兩種模式的應用。

迭代器模式

迭代器模式是一種行為設計模式,它允許我們在不暴露底層實作細節的情況下,依序存取一個聚合物件中的各個元素。這種模式在處理集合資料結構,如列表、樹或圖時特別有用。

迭代器模式的實作

以下是一個使用迭代器模式的範例,我們將建立一個FootballTeam類別來代表一支足球隊,並使用迭代器來遍歷隊伍中的成員:

class FootballTeamIterator:
    def __init__(self, members):
        self.members = members
        self.index = 0

    def __iter__(self):
        return self

    def __next__(self):
        if self.index >= len(self.members):
            raise StopIteration
        member = self.members[self.index]
        self.index += 1
        return member

class FootballTeam:
    def __init__(self, members):
        self.members = members

    def __iter__(self):
        return FootballTeamIterator(self.members)

def main():
    members = [f"player{str(x)}" for x in range(1, 23)]
    members += ["coach1", "coach2", "coach3"]
    team = FootballTeam(members)
    team_it = iter(team)
    try:
        while True:
            print(next(team_it))
    except StopIteration:
        print("(結束)")

if __name__ == "__main__":
    main()

迭代器模式的運作流程

  1. 我們定義了一個FootballTeamIterator類別來實作迭代器介面。
  2. FootballTeam類別包含了一個__iter__方法,該方法傳回一個FootballTeamIterator例項。
  3. main函式中,我們建立了一個FootballTeam例項,並使用iter()函式取得其迭代器。
  4. 我們使用一個無限迴圈來遍歷迭代器中的元素,直到觸發StopIteration例外。

範本方法模式

範本方法模式是一種行為設計模式,它定義了一個演算法的骨架,將某些步驟的實作延遲到子類別中。這種模式允許我們在不改變演算法結構的情況下,重新定義某些步驟的行為。

範本方法模式的實作

以下是一個使用範本方法模式的範例,我們將建立一個橫幅產生器,根據不同的樣式產生不同的橫幅:

圖表翻譯:

此圖示展示了範本方法模式的實作流程。我們首先定義一個範本方法,接著實作基本的樣式,然後擴展出特定的樣式,最後生成橫幅。這個流程清晰地說明瞭範本方法模式的結構和擴充套件性。

def generate_banner(msg, style):
    print("-- 橫幅開始 --")
    print(style(msg))
    print("-- 橫幅結束 --\n")

def dots_style(msg):
    msg = msg.capitalize()
    ten_dots = "." * 10
    msg = f"{ten_dots}{msg}{ten_dots}"
    return msg

def admire_style(msg):
    msg = msg.upper()
    return "!".join(msg)

def cow_style(msg):
    import cowpy.cow
    msg = cowpy.cow.milk_random_cow(msg)
    return msg

def main():
    styles = (dots_style, admire_style, cow_style)
    msg = "快樂程式設計"
    for style in styles:
        generate_banner(msg, style)

if __name__ == "__main__":
    main()

範本方法模式的運作流程

  1. 我們定義了一個generate_banner函式作為範本方法,它接受訊息和樣式作為引數。
  2. 我們實作了多種不同的樣式函式,如dots_styleadmire_stylecow_style
  3. main函式中,我們將不同的樣式函式應用於相同的訊息,產生不同的橫幅。

行為設計模式的深入探討

在軟體開發領域中,行為設計模式扮演著至關重要的角色,它們幫助開發者解決複雜的物件互動問題,並提升程式碼的可維護性和擴充套件性。本文將深入探討多種行為設計模式,並結合Python語言的特性,展示如何在實際開發中應用這些模式。

中介者模式(Mediator Pattern)

中介者模式是一種行為設計模式,它透過引入一個中介者物件來管理多個物件之間的互動,從而降低物件之間的耦合度。在中介者模式中,物件之間不再直接進行通訊,而是透過中介者物件來協調彼此的互動。

圖表翻譯:

此圖示展示了中介者模式的基本架構。物件1和物件2透過通知中介者來間接與其他物件進行互動。中介者負責協調物件3和物件4的行為,從而實作物件之間的解耦。

存取者模式(Visitor Pattern)

存取者模式是一種將演算法與其操作的物件分離的設計模式。它允許在不修改物件結構的前提下,新增新的操作或演算法。

class Visitor:
 def visit(self, element):
 pass

class ConcreteVisitor(Visitor):
 def visit(self, element):
 print(f"存取者正在存取 {element}")

class Element:
 def accept(self, visitor):
 visitor.visit(self)

# 使用範例
element = Element()
visitor = ConcreteVisitor()
element.accept(visitor)

內容解密:

此程式碼展示了存取者模式的基本實作。Visitor類別定義了存取者的介面,而ConcreteVisitor類別實作了具體的存取邏輯。Element類別則定義了接受存取者的方法,從而實作了物件與存取者之間的互動。

其他行為設計模式

除了中介者模式和存取者模式之外,設計模式的經典目錄中還包含了其他多種行為設計模式,如責任鏈模式、命令模式、觀察者模式、狀態模式、直譯器模式、策略模式、備忘錄模式和範本方法模式等。這些模式各有其特點和適用場景,能夠有效地解決各種軟體設計問題。

隨著軟體開發技術的不斷進步,新的設計模式和架構模式不斷湧現。未來,我們將繼續探索更多先進的設計模式和技術,以滿足日益複雜的軟體開發需求。同時,我們也將繼續關注Python語言的新特性和最佳實踐,以更好地應用行為設計模式於實際開發中。

行為設計模式的實踐應用

在實際開發中,行為設計模式能夠幫助我們解決多種軟體設計問題。以下是一些實踐應用的範例:

責任鏈模式(Chain of Responsibility Pattern)

責任鏈模式用於簡化複雜的處理流程,使得請求能夠沿著處理鏈進行傳遞,直到找到合適的處理者。

class Handler:
 def set_next(self, handler):
 self.next_handler = handler
 return handler

 def handle(self, request):
 if hasattr(self, 'next_handler'):
 self.next_handler.handle(request)

class ConcreteHandler1(Handler):
 def handle(self, request):
 if request == "請求1":
 print("處理請求1")
 else:
 super().handle(request)

# 使用範例
handler1 = ConcreteHandler1()
handler2 = ConcreteHandler2()
handler1.set_next(handler2)
handler1.handle("請求1")

內容解密:

此程式碼展示了責任鏈模式的基本實作。Handler類別定義了處理者的基本介面,而ConcreteHandler1ConcreteHandler2類別實作了具體的處理邏輯。透過設定處理鏈,能夠實作請求的順序處理。

命令模式(Command Pattern)

命令模式將請求封裝為物件,從而能夠支援可復原的操作和請求佇列。

class Command:
 def execute(self):
 pass

class ConcreteCommand(Command):
 def execute(self):
 print("執行命令")

class Invoker:
 def set_command(self, command):
 self.command = command

 def execute_command(self):
 self.command.execute()

# 使用範例
command = ConcreteCommand()
invoker = Invoker()
invoker.set_command(command)
invoker.execute_command()

內容解密:

此程式碼展示了命令模式的基本實作。Command類別定義了命令的介面,而ConcreteCommand類別實作了具體的命令邏輯。Invoker類別負責執行命令,從而實作了請求的封裝和執行。

架構設計模式

在前一章中,我們探討了行為模式,這些模式有助於物件之間的互聯和演算法。下一類別設計模式是架構設計模式。這些模式提供了一個範本,用於解決常見的架構問題,促進可擴充套件、可維護和可重複使用系統的開發。

本章涵蓋的主題

• Model-View-Controller (MVC) 模式 • 微服務模式 • 無伺服器模式 • 事件溯源模式 • 其他架構設計模式

在本章結束時,您將瞭解如何使用流行的架構設計模式構建強壯且靈活的軟體。

技術需求

參見第1章中提出的技術需求。本章討論的程式碼的額外技術需求如下: • 對於微服務模式部分,請安裝以下內容:

  • gRPC,使用以下命令:python -m pip install grpcio
  • gRPC-tools,使用以下命令:python -m pip install grpcio-tools
  • Lanarky及其依賴項,使用以下命令:python -m pip install "lanarky[openai]"==0.8.6 uvicorn==0.29.0(注意:在撰寫本文時,這與Python 3.12不相容。您可以改用Python 3.11來重現相關範例。)

• 對於無伺服器模式部分,請安裝以下內容:

  • Docker
  • LocalStack,用於在本地測試AWS Lambda,使用以下命令:python -m pip install localstack(注意:在撰寫本文時,這與Python 3.12不相容。您可以改用Python 3.11。)
  • awscli-local,使用以下命令:python -m pip install awscli-local
  • awscli,使用以下命令:python -m pip install awscli

• 對於事件溯源部分,請安裝以下內容:

  • eventsourcing,使用以下命令:python -m pip install eventsourcing

MVC 模式

MVC 模式是鬆散耦合原則的另一種應用。該模式的名稱來自用於分割軟體應用的三個主要元件:模型、檢視和控制器。

即使我們永遠不必從頭開始實作它,我們也需要熟悉它,因為所有常見的框架都使用MVC或其稍微不同的版本(稍後會詳細介紹)。

模型、檢視和控制器的角色

  • 模型 是核心元件,代表知識,包含並管理應用的(業務)邏輯、資料、狀態和規則。
  • 檢視 是模型的視覺表示,例如電腦GUI、電腦終端機的文字輸出、智慧型手機應用程式GUI、PDF檔案、圓餅圖、長條圖等。檢視僅顯示資料,不處理資料。
  • 控制器 是模型和檢視之間的連結/膠水,所有模型和檢視之間的通訊都透過控制器進行。

MVC 應用流程

  1. 使用者透過點選按鈕觸發檢視。
  2. 檢視將使用者的動作通知控制器。
  3. 控制器處理使用者輸入並與模型互動。
  4. 模型執行所有必要的驗證和狀態更改,並通知控制器應執行的操作。
  5. 控制器指示檢視更新並適當地顯示輸出,遵循模型的指示。
@startuml
skinparam backgroundColor #FEFEFE
skinparam componentStyle rectangle

title Python 行為與架構設計模式解析

package "Python 應用架構" {
    package "應用層" {
        component [主程式] as main
        component [模組/套件] as modules
        component [設定檔] as config
    }

    package "框架層" {
        component [Web 框架] as web
        component [ORM] as orm
        component [非同步處理] as async
    }

    package "資料層" {
        database [資料庫] as db
        component [快取] as cache
        component [檔案系統] as fs
    }
}

main --> modules : 匯入模組
main --> config : 載入設定
modules --> web : HTTP 處理
web --> orm : 資料操作
orm --> db : 持久化
web --> cache : 快取查詢
web --> async : 背景任務
async --> fs : 檔案處理

note right of web
  Flask / FastAPI / Django
end note

@enduml

圖表翻譯:

此圖示展示了MVC模式下使用者與應用互動的基本流程。流程始於使用者觸發檢視,接著檢視將使用者的動作通知控制器。控制器處理後與模型互動,模型完成必要處理後再通知控制器。最後,控制器根據模型的指示更新檢視,完成了整個互動流程。

MVC 模式的真實範例

MVC 是關注點分離原則的應用。關注點分離在現實生活中被廣泛使用。例如,在建造新房時,您通常會將不同的專業人士分配給不同的任務,如安裝水管和電力系統、以及油漆房屋。

另一個例子是餐廳。服務生接收訂單並將餐點送給顧客,但餐點是由廚師準備的。

在網頁開發中,許多框架使用MVC理念,例如:

  • Web2py 框架是一個輕量級的Python框架,採用MVC模式。
  • Django 框架雖然使用了不同的命名慣例,但本質上也是MVC模式的變體,被稱為Model-View-Template (MVT)。

MVC 模式的應用場景

MVC 是一個非常通用和有用的設計模式。事實上,所有流行的網頁框架(Django、Rails、Symfony和Yii)和應用程式框架(iPhone SDK、Android和QT)都使用MVC或其變體(如MVA、MVP或MVT)。

即使我們不使用任何這些框架,自己實作該模式也是有意義的,因為它提供了以下好處: • 檢視和模型之間的分離允許圖形設計師專注於使用者介面部分,而程式設計師可以專注於開發,互不幹擾。 • 由於檢視和模型之間的鬆散耦合,每個部分都可以被修改/擴充套件而不影響另一個部分。例如,新增一個新的檢視是微不足道的,只需為其實作一個新的控制器即可。 • 維護每個部分都更容易,因為職責清晰。

在從頭實作MVC時,請確保您建立了聰明的模型、薄的控制器和笨的檢視。

程式碼範例

# MVC模式範例程式碼
class Model:
 def __init__(self):
 self.data = None

 def set_data(self, data):
 self.data = data

 def get_data(self):
 return self.data

class View:
 def update(self, data):
 print(f"檢視更新:{data}")

class Controller:
 def __init__(self, model, view):
 self.model = model
 self.view = view

 def set_data(self, data):
 self.model.set_data(data)
 self.view.update(self.model.get_data())

# 使用範例
model = Model()
view = View()
controller = Controller(model, view)

controller.set_data("新的資料")

內容解密:

此程式碼展示了一個簡單的MVC模式實作。Model類別負責儲存和管理資料,View類別負責顯示資料,而Controller類別則負責協調ModelView之間的互動。當呼叫Controllerset_data方法時,它會更新Model的資料,並隨後更新View以顯示最新的資料。這種設計實作了模型、檢視和控制器之間的清晰分離,提高了程式碼的可維護性和可擴充套件性。