前端設計模式(Design Patterns)

avatar

Merano Tu

2025/3/4

這裡是一些常見的前端設計模式(Design Patterns),並提供實際使用的例子來說明它們在前端開發中的應用。
這些設計模式主要用於解決常見的前端問題,提升代碼的結構化、可維護性和可擴展性。
以下是幾個主要的設計模式及其應用:

1. 模塊模式 (Module Pattern)

=> 封裝公有私有

描述:

模塊模式通過封裝邏輯,將私有變量和方法與公開的API分離,減少全局命名空間的污染。

使用場景:

  • 組織代碼,避免全局變量衝突。
  • 在較小的應用中實現簡單的數據隱藏。

實際例子:

假設你正在開發一個計數器功能:

const Counter = (function () {
  let count = 0; // 私有變量

  return {
    increment: function () {
      count++;
      console.log(count);
    },
    decrement: function () {
      count--;
      console.log(count);
    },
    getCount: function () {
      return count;
    }
  };
})();

Counter.increment(); // 1
Counter.increment(); // 2
Counter.decrement(); // 1
console.log(Counter.getCount()); // 1

在這個例子中,count 是私有的,外部只能通過公開的方法來操作計數器。


2. 觀察者模式 (Observer Pattern)

=>事件監聽、訂閱

描述:

觀察者模式定義了一個對象(主題)與多個觀察者之間的依賴關係,當主題狀態改變時,所有觀察者會自動收到通知。

使用場景

  • 事件監聽(如按鈕點擊)。
  • 在前端框架(如 React 或 Vue)中實現狀態管理

實際例子:

一個簡單的事件訂閱與發布系統:

class EventEmitter {
  constructor() {
    this.listeners = {};
  }

  on(event, callback) {
    if (!this.listeners[event]) {
      this.listeners[event] = [];
    }
    this.listeners[event].push(callback);
  }

  emit(event, data) {
    if (this.listeners[event]) {
      this.listeners[event].forEach(callback => callback(data));
    }
  }
}

const emitter = new EventEmitter();
emitter.on('click', (data) => console.log(`Clicked: ${data}`));
emitter.emit('click', 'Button 1'); // 輸出: Clicked: Button 1

在實際應用中,這可以用於監聽用戶交互,例如點擊按鈕後觸發多個回調 (callback)。


3. 單例模式 (Singleton Pattern)

-> enum、Redux 全域狀態管理

描述:

單例模式確保一個類只有一個實例,並提供全局訪問點。

使用場景:

  • 配置管理器、全局狀態存儲(如 Redux store)。

實際例子:

假設你需要一個全局的配置對象:

class Config {
  constructor() {
    if (!Config.instance) {
      this.settings = { theme: 'light', lang: 'en' };
      Config.instance = this;
    }
    return Config.instance;
  }

  getSetting(key) {
    return this.settings[key];
  }
}

const config1 = new Config();
const config2 = new Config();
console.log(config1 === config2); // true
console.log(config1.getSetting('theme')); // 'light'

這裡,不管創建多少次 Config,都只會返回同一個實例。


4. 工廠模式 (Factory Pattern)

=> 可複用元件

描述:

工廠模式通過一個工廠函數或類來創建對象,而不需要直接使用 new 關鍵字。

使用場景:

  • 動態創建不同類型的 UI 組件。
  • 根據條件生成不同的實例。

實際例子:

假設你需要根據類型生成不同的按鈕:

class ButtonFactory {
  static createButton(type) {
    switch (type) {
      case 'primary':
        return { text: 'Primary Button', style: 'blue' };
      case 'secondary':
        return { text: 'Secondary Button', style: 'gray' };
      default:
        return { text: 'Default Button', style: 'black' };
    }
  }
}

const primaryBtn = ButtonFactory.createButton('primary');
console.log(primaryBtn); // { text: 'Primary Button', style: 'blue' }

在 React 中,這可以用於根據 props 動態生成組件。


5. 裝飾者模式 (Decorator Pattern)

描述:

裝飾者模式允許在不修改原有對象的情況下,動態地為對象添加功能。

使用場景:

  • 為現有組件添加額外的行為(如日誌記錄、驗證)。

實際例子:

假設你有一個發送請求的功能,想添加日誌功能:

function fetchData(url) {
  console.log(`Fetching data from ${url}`);
  return Promise.resolve('Data');
}

function withLogging(fetchFn) {
  return function (url) {
    console.log(`Log: Starting request to ${url}`);
    return fetchFn(url).then(data => {
      console.log(`Log: Request completed`);
      return data;
    });
  };
}

const loggedFetch = withLogging(fetchData);
loggedFetch('https://api.example.com');
// 輸出:
// Log: Starting request to https://api.example.com
// Fetching data from https://api.example.com
// Log: Request completed

這裡,withLogging 是一個裝飾者,為 fetchData 增加了日誌功能。


6. MVC 模式 (Model-View-Controller)

描述:

MVC 將應用分成模型(數據)、視圖(UI)和控制器(邏輯)三部分。

MVC 的理念

MVC 是一種經典的設計模式,最初由 Trygve Reenskaug 在 1970 年代提出,用於 Smalltalk 系統。它的核心目標是將應用程序的邏輯分為三個相互關聯的部分,從而實現關注點分離(Separation of Concerns),提高代碼的可維護性和可擴展性。

1. 三個核心組件

  • Model(模型)

    • 作用:負責數據的管理、業務邏輯和存儲。它是應用程序的「真相之源」(source of truth)。

    • 職責

      • 存儲數據(例如從數據庫或 API 獲取)。
      • 處理數據邏輯(如計算、驗證)。
      • 在數據更新時通知視圖(通常通過觀察者模式)。
    • 例子:一個購物車的數據結構,包含商品列表、總價計算邏輯等。

  • View(視圖)

    • 作用:負責顯示數據給用戶,是用戶與應用交互的界面。
    • 職責
      • 呈現 Model 的數據。
      • 將用戶的操作(點擊、輸入等)傳遞給 Controller。
      • 不直接處理業務邏輯,只專注於展示。
    • 例子:HTML 頁面中的購物車表格,顯示商品名稱和價格。
  • Controller(控制器)

    • 作用:作為 Model 和 View 之間的橋樑,處理用戶輸入並更新數據。
    • 職責
      • 接收用戶的操作(通過 View)。
      • 更新 Model 的狀態。
      • 根據需要觸發 View 的更新。
    • 例子:當用戶點擊「添加商品」按鈕時,Controller 將新商品添加到 Model,並通知 View 重新渲染。

2. 工作流程

  1. 用戶與 View 交互(例如點擊按鈕)。
  2. View 將用戶的操作傳遞給 Controller。
  3. Controller 修改 Model 的數據或狀態。
  4. Model 更新後,通知 View(或通過 Controller 間接通知)。
  5. View 根據 Model 的新狀態重新渲染。

這種單向數據流(View → Controller → Model → View)確保了數據與展示的清晰分離。

實際例子:

一個簡單的計數器應用:

// Model 模型(數據)
const model = {
  count: 0,
  updateCount(value) {
    this.count += value;
    view.render(this.count);
  }
};

// View 視圖(UI)
// 跟畫面之間的互動 
const view = {
  render(count) {
    document.getElementById('count').textContent = count;
  }
};

// Controller 控制器(邏輯)
// 控制執行
const controller = {
  increment() {
    model.updateCount(1);
  },
  decrement() {
    model.updateCount(-1);
  }
};

// HTML: <button onclick="controller.increment()">+</button>
//       <button onclick="controller.decrement()">-</button>
//       <span id="count">0</span>

總結

這些前端設計模式在實際開發中非常常見,尤其是在需要構建可擴展和可維護的應用時。以下是它們的典型應用場景總結:

  • 模塊模式:小型項目或工具庫。
  • 觀察者模式:事件驅動的 UI 更新。
  • 單例模式:全局狀態或配置。
  • 工廠模式:組件或對象的動態創建。
  • 裝飾者模式:功能增強。
  • MVC:結構化大型應用。

與 grok 協作

相關資料:
前端也有 DESIGN PATTERNS

回到文章列表頁

© 2024 Merano Tu. All rights reserved.