首頁 >後端開發 >Python教學 >分解依賴倒置、IoC 和 DI

分解依賴倒置、IoC 和 DI

DDD
DDD原創
2025-01-20 16:26:09282瀏覽

Breaking Down Dependency Inversion, IoC, and DI

探索 NestJS 的依賴注入系統引發了對依賴反轉、控制反轉和依賴注入的更深入研究。 這些概念雖然看似相似,但卻為不同的問題提供了不同的解決方案。 此解釋可作為個人複習,並希望能為其他處理這些術語的人提供有用的指南。


  1. 依賴倒置原則(DIP)

定義:高層模組不應該依賴低層模組;兩者都應該依賴抽象。抽像不應該依賴細節;細節應該取決於抽象。

這代表什麼:

在軟體中,高層模組封裝核心業務邏輯,而低層模組處理特定的實作(資料庫、API 等)。 如果沒有 DIP,高層模組直接依賴低層模組,造成緊密耦合,阻礙靈活性,使測試和維護複雜化,並且使替換或擴展低層細節變得困難。

DIP 顛倒了這種關係。高層和低層模組都依賴共享抽象(介面或抽象類別),而不是直接控制。


無 DIP

Python 範例

<code class="language-python">class EmailService:
    def send_email(self, message):
        print(f"Sending email: {message}")

class Notification:
    def __init__(self):
        self.email_service = EmailService()

    def notify(self, message):
        self.email_service.send_email(message)</code>

TypeScript 範例

<code class="language-typescript">class EmailService {
    sendEmail(message: string): void {
        console.log(`Sending email: ${message}`);
    }
}

class Notification {
    private emailService: EmailService;

    constructor() {
        this.emailService = new EmailService();
    }

    notify(message: string): void {
        this.emailService.sendEmail(message);
    }
}</code>

問題:

  1. 緊密耦合:Notification直接依賴EmailService
  2. 擴充性有限:切換到SMSService需要修改Notification

含浸

Python 範例

<code class="language-python">from abc import ABC, abstractmethod

class MessageService(ABC):
    @abstractmethod
    def send_message(self, message):
        pass

class EmailService(MessageService):
    def send_message(self, message):
        print(f"Sending email: {message}")

class Notification:
    def __init__(self, message_service: MessageService):
        self.message_service = message_service

    def notify(self, message):
        self.message_service.send_message(message)

# Usage
email_service = EmailService()
notification = Notification(email_service)
notification.notify("Hello, Dependency Inversion!")</code>

TypeScript 範例

<code class="language-typescript">interface MessageService {
    sendMessage(message: string): void;
}

class EmailService implements MessageService {
    sendMessage(message: string): void {
        console.log(`Sending email: ${message}`);
    }
}

class Notification {
    private messageService: MessageService;

    constructor(messageService: MessageService) {
        this.messageService = messageService;
    }

    notify(message: string): void {
        this.messageService.sendMessage(message);
    }
}

// Usage
const emailService = new EmailService();
const notification = new Notification(emailService);
notification.notify("Hello, Dependency Inversion!");</code>

DIP 的好處:

  • 靈活性:輕鬆交換實作。
  • 可測試性:使用模擬進行檢定。
  • 可維護性:低階模組的變更不會影響高階模組。

  1. 控制反轉 (IoC)

IoC 是一種設計原則,其中依賴控制轉移到外部系統(框架)而不是在類別內進行管理。 傳統上,類別會建立並管理其相依性。 IoC 逆轉了這一點——外部實體注入依賴項。


Python 範例:沒有 IoC

<code class="language-python">class SMSService:
    def send_message(self, message):
        print(f"Sending SMS: {message}")

class Notification:
    def __init__(self):
        self.sms_service = SMSService()  # Dependency created internally

    def notify(self, message):
        self.sms_service.send_message(message)</code>

TypeScript 範例:沒有 IoC

<code class="language-typescript">class SMSService {
    sendMessage(message: string): void {
        console.log(`Sending SMS: ${message}`);
    }
}

class Notification {
    private smsService: SMSService;

    constructor() {
        this.smsService = new SMSService(); // Dependency created internally
    }

    notify(message: string): void {
        this.smsService.sendMessage(message);
    }
}</code>

沒有 IoC 的問題:

  1. 緊密耦合。
  2. 靈活性低。
  3. 困難的檢定。

Python 範例:使用 IoC

<code class="language-python">class EmailService:
    def send_email(self, message):
        print(f"Sending email: {message}")

class Notification:
    def __init__(self):
        self.email_service = EmailService()

    def notify(self, message):
        self.email_service.send_email(message)</code>

TypeScript 範例:使用 IoC

<code class="language-typescript">class EmailService {
    sendEmail(message: string): void {
        console.log(`Sending email: ${message}`);
    }
}

class Notification {
    private emailService: EmailService;

    constructor() {
        this.emailService = new EmailService();
    }

    notify(message: string): void {
        this.emailService.sendEmail(message);
    }
}</code>

國際奧委會的好處:

  1. 鬆散耦合。
  2. 輕鬆實現切換。
  3. 提高了可測試性。

  1. 依賴注入 (DI)

DI 是一種物件從外部來源接收其相依性的技術。 這是 IoC 的實際實現,透過以下方式註入依賴項:

  1. 建構函式註入
  2. 二傳手注射
  3. 介面注入

Python 範例:DI 框架(使用 injector 函式庫)

<code class="language-python">from abc import ABC, abstractmethod

class MessageService(ABC):
    @abstractmethod
    def send_message(self, message):
        pass

class EmailService(MessageService):
    def send_message(self, message):
        print(f"Sending email: {message}")

class Notification:
    def __init__(self, message_service: MessageService):
        self.message_service = message_service

    def notify(self, message):
        self.message_service.send_message(message)

# Usage
email_service = EmailService()
notification = Notification(email_service)
notification.notify("Hello, Dependency Inversion!")</code>

TypeScript 範例:DI 框架(使用 tsyringe 函式庫)

<code class="language-typescript">interface MessageService {
    sendMessage(message: string): void;
}

class EmailService implements MessageService {
    sendMessage(message: string): void {
        console.log(`Sending email: ${message}`);
    }
}

class Notification {
    private messageService: MessageService;

    constructor(messageService: MessageService) {
        this.messageService = messageService;
    }

    notify(message: string): void {
        this.messageService.sendMessage(message);
    }
}

// Usage
const emailService = new EmailService();
const notification = new Notification(emailService);
notification.notify("Hello, Dependency Inversion!");</code>

DI 的好處:

  • 簡化測試。
  • 提高了可擴充性。
  • 增強的可維護性。

這個詳細的解釋闡明了 DIP、IoC 和 DI 之間的關係和區別,強調了它們對構建健壯且可維護的軟體的個人貢獻。

以上是分解依賴倒置、IoC 和 DI的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn