首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 網頁程式設計 >> PHP 程式設計 >> PHP 綜合知識

PHP 面向物件設計 61 條核心經驗總結

     編輯:PHP 綜合知識

前言

面向物件設計(OOD)不僅是語法糖,更是管理複雜性的思維框架。以下 61 條經驗法則源自經典軟體工程實踐,經過 PHP 語境適配整理,旨在幫助開發者構建高內聚、低耦合、可維護、可擴展的系統。

核心原則分類總覽

類別條目範圍核心思想
類與介面設計1-15封裝、介面最小化、職責單一、避免上帝類
耦合與內聚7, 9, 10, 14, 15, 22-25零耦合或導出耦合、相關數據行為集中、減少協作者
繼承與多態29, 36-51僅用於特化層次、里氏替換、避免深層繼承、組合優於繼承
約束與契約30-33語義約束內建、集中式 vs 分散式權衡
包含與關聯26, 28, 34, 35, 58包含即使用、對象數量限制、共享作用域無使用關係
全域狀態與物理設計59, 60類變量替代全域、邏輯設計優先於物理設計
狀態修改規範2, 61依賴公開介面、不繞過介面修改狀態

精選 20 條高頻實踐指南

1. 數據封裝(條目 1, 5, 38)

所有數據隱藏於類內部,僅透過公開介面存取。私有輔助方法不屬於公開介面,不應暴露。

2. 介面最小化(條目 3, 6, 14)

減少公開訊息數量。大量 get/set 方法暗示數據與行為未集中,應重構為行為豐富的領域模型,而非貧血模型。

3. 單一職責與避免上帝類(條目 8, 13)

類應僅代表一個關鍵抽象。警惕命名含 Manager、System、Driver、Subsystem 的類,往往是職責過重的信號。

4. 依賴倒置與穩定方向(條目 10)

朝向穩定方向依賴。依賴抽象(介面)而非具體實現,高層模組不應依賴低層模組,二者皆應依賴抽象。

5. 繼承紀律(條目 36-43, 49-51)

  • 繼承僅用於建模「is-a」特化層次(條目 36, 56)
  • 基類應為抽象類,派生類必須知道基類,基類不知派生類(條目 37, 41, 42)
  • 基類數據應為私有,避免 protected 數據洩露實作細節(條目 38)
  • 繼承深度理論上越深越好,實踐中不超過 6 層(條目 39, 40)
  • 共同數據/行為上移至基類(條目 43, 45),共同介面僅在需要多態時提取(條目 46)
  • 禁止用繼承建模動態語義(條目 49),禁止將對象變為派生類(條目 50)

6. 組合優於繼承(條目 53, 58)

可選包含關係勿建模為繼承。面臨包含與關聯選擇時,優先選擇包含(條目 58)。

7. 多態替代條件分支(條目 47, 48)

顯式類型判斷(if ($obj instanceof A))通常違反開閉原則,應用多態機制。屬性值驅動的分支應重構為繼承體系,每個值對應一個派生類。

8. 類大小與複雜度控制(條目 22-25, 27, 28)

  • 協作者數量最小化(條目 22)
  • 類與協作者間訊息傳遞最小化(條目 23, 24)
  • 扇出(定義訊息數 × 發送訊息數)最小化(條目 25)
  • 方法應使用大多數數據成員(條目 27)
  • 類包含對象數不超過短期記憶容量(6±2,條目 28)

9. 約束實作策略(條目 30-33)

  • 靜態不變約束 → 構造函數驗證(條目 31)
  • 頻繁變動的語義信息 → 集中式第三方對象(條目 32)
  • 穩定的語義信息 → 分散在相關類中(條目 33)

10. 物件狀態修改規範(條目 61)

嚴禁繞過公開介面直接修改對象狀態。所有狀態變更必須透過方法調用,保證不變約束檢查、事件觸發、日誌記錄等橫切關注點生效。

PHP 語境下的具體落地建議

介面與抽象類

// 定義穩定契約
interface UserRepository {
    public function findById(string $id): ?User;
    public function save(User $user): void;
}

// 具體實現依賴抽象
class MySQLUserRepository implements UserRepository {
    // ...
}

class UserService {
    public function __construct(private UserRepository $repo) {} // 依賴注入
}

避免貧血模型


// ❌ 貧血模型:只有 get/set,業務邏輯分散在 Service 中
class Order {
    private $status;
    public function getStatus() { return $this->status; }
    public function setStatus($s) { $this->status = $s; }
}

// ✅ 充血模型:封裝業務規則
class Order {
    private $status = 'pending';
    public function pay(): void {
        if ($this->status !== 'pending') throw new \LogicException('訂單狀態不允許支付');
        $this->status = 'paid';
        $this->recordEvent(new OrderPaid($this->id));
    }
}

組合替代繼承


// ❌ 繼承爆炸:LoggerInterface, FileLogger, DBLogger, EmailLogger...
// ✅ 組合策略
interface LogHandler { public function handle(string $msg): void; }

class Logger {
    public function __construct(private iterable $handlers) {}
    public function log(string $msg): void {
        foreach ($this->handlers as $h) $h->handle($msg);
    }
}

總結

這 61 條經驗不是教條,而是導航燈。實際專案中需根據團隊規模、業務複雜度、交付壓力權衡取捨。核心心法只有八字:高內聚、低耦合、單一職責、依賴抽象。持續重構、代碼審查、架構評審,才能讓設計原則真正落地生根。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved