嘿!

我最近瀏覽了多個知識資源,以了解有關 Node.js 中流行設計和架構模式的更多資訊。我的目標主要是伺服器(後端)端,但當我瀏覽它們時,我發現它們與瀏覽器(前端)框架有很多相似之處。其中一些甚至直接在框架中使用,對此我更高興,因為我已經在不知不覺中使用它們了😉

您可以使用許多(確實很多)設計模式,因此在本文中,我決定選擇其中 10 種並更詳細地解釋它們。

享受!

🟢什麼是設計模式?

設計模式是經過驗證和久經考驗的解決方案,可以解決我們作為開發人員每天遇到的問題。這些模式有助於推廣最佳實踐並實施結構化方法來解決設計和開發軟體架構時的日常問題。軟體工程師可以使用這些模式開發可維護、安全且穩定的系統。

Node.js 由於其靈活性,不會強迫您遵循某些模式,而是讓您可以自由地選擇任務所需的模式。這就是為什麼我認為它今天被如此廣泛使用(順便說一下,這要感謝 JavaScript :D)。

✅ Node.js 中五種流行的設計模式

下面,您將看到我喜歡的 5 種精選設計模式的清單。

Singleton

這種模式是關於只能有一個實例並提供對其的全域存取的類別。 Node.js 中的模組可以在應用程式中快取和共享,這將有助於提高資源效率。這種單例模式的常見範例是用於連接某些第三方服務(例如資料庫、快取服務、電子郵件提供者等)的模組,該模組在 Nest.js 框架中廣泛使用。讓我們來看看下面的例子:

class Redis {
  constructor() {
    this.connection = null;
  }

  static getInstance() {
    if (!Redis.instance) {
      Redis.instance = new Redis(options);
    }

    return Redis.instance;
  }

  connect() {
    this.connection = 'Redis connected'
  }
}

然後我們可以像下面這樣使用它:

const medicine = Redis.getInstance();
const redisTwo = Redis.getInstance();

console.log(redisOne === RedisTwo); // it will result to `true`

redisOne.connect();

console.log(redisOne.connection) // 'Redis connected'
console.log(redisTwo.connection) // 'Redis connected'

這種方法可確保只有一個與 Redis 的連接,並防止重複連接。

Factory

使用此模式,您可以建立新物件,而無需指定將建立的物件的類別。多虧了它,我們抽象化了物件建立,這有助於提高程式碼的可讀性和可重用性:

class Character {
  constructor(type, health) {
    this.type = type;
    this.health = health;
  }
}

class CharacterFactory {
  createCharacter(name) {
    switch(name) {
      case 'mage': 
        return new Character('Powerful Mage', 8);
      case 'warrior':
        return new Character('Courageous Warrior', 10);
      case 'rogue':
        return new Character('Sneaky Rogue', 9)
      default:
        return new Error('Unknown character');
    }
  }
}

然後我們可以像下面這樣使用它:

const characterFactory = new CharacterFactory();

const mage = characterFactory.createCharacter('mage');
const warrior = characterFactory.createCharacter('warrior');

console.log(mage.type) // Powerful Mage
console.log(warrior.type) // Courageous Warrior

這種方法允許該工廠的使用者使用工廠程式碼,而不是直接使用Character類別建構函數。

Observer

此模式的工作方式是,您將擁有一個實體來管理稱為觀察者的依賴元素列表,並在狀態變更時通知它們。此模式在 Vue.js 框架中廣泛使用,實作方式如下:

class Topic {
  constructor() {
    this.observers = []; 
  }

  subscribe(observer) {
    this.observers.push(observer);
  }

  unsubscribe(observer) {
    this.observers = this.observers.filter(o => o !== observer);
  }

  notify(data) {
    this.observers.forEach(o => o.update(data));
  }
}

class Observer {
  constructor(name) {
    this.name = name;
  }

  update(data) {
    console.log(`${this.name} received ${data}`);
  }
}

您可以像下面這樣使用它:

const topic = new Topic();

const observer1 = new Observer('Observer 1');
const observer2 = new Observer('Observer 2');

topic.subscribe(observer1);
topic.subscribe(observer2);

topic.notify('Hello World');
// Observer 1 received Hello World 
// Observer 2 received Hello World

topic.unsubscribe(observer2);

topic.notify('Hello Again');
// Observer 1 received Hello Again

對於事件處理和非同步工作流程來說,這是一種非常有用的模式,允許更新多個物件,而無需將發布者與訂閱者耦合。

Decorator

這種模式對於使用新功能擴展現有功能而不影響初始/原始實例非常有用。由於 TypeScript 的全面支持,它在 Nest.js 框架中被廣泛使用,但在常規 Node.js 中,它可以用於以下用途:

class Character {
  constructor() {
    this.endurance = 10;
  }

  getEndurance() {
    return this.endurance;
  }
}

class CharacterActions {
  constructor(character) {
    this.character = character;
  }

  attack() {
    this.character.endurance -= 2;
  }

  rest() {
    this.character.endurance += 1; 
  }
}

然後可以像下面這樣使用它:

const character = new Character();

console.log(character.getEndurance()); // 10

const characterWithActions = new CharacterActions(character);

characterWithActions.attack(); // - 2
characterWithActions.rest(); // + 1

console.log(characterWithActions.character.getEndurance()); // 9

透過使用這種模式,我們可以輕鬆地擴展已經存在的類,而不影響它們的核心功能。

依賴注入

在此模式中,類別或模組從外部來源接收依賴項,而不是在內部註冊它們。這種方法允許從系統中提取某些可重複使用元素,以便於測試和維護。它在 Nest.js 框架中被廣泛使用。它可以像下面這樣實現:

class UserService {
  constructor(databaseService, loggerService) {
    this.db = databaseService;
    this.logger = loggerService;
  }

  async getUser(userId) {
    const user = await this.db.findUserById(userId);
    this.logger.log(`Fetched user ${user.name}`);
    return user;
  }
}

然後,您可以像下面這樣使用它:

const databaseService = new Database();
const loggerService = new Logger();

const userService = new UserService(databaseService, loggerService);

userService.getUser(1);

這種方法允許您將系統的元素提取到可以在需要時注入的獨立實體中。

📖 了解更多

如果您想了解有關 Vue、Nuxt、JavaScript 或其他有用技術的更多訊息,請單擊此連結或單擊下圖查看 VueSchool:

Vue 學校連結

它涵蓋了建立現代 Vue 或 Nuxt 應用程式時最重要的概念,可以幫助您完成日常工作或業餘專案😉

✅ 總結

幹得好!您剛剛了解了某些設計模式在 Node.js 中的工作原理以及如何實作它們。

保重,下次見!

一如既往地快樂編碼🖥️


原文出處:https://dev.to/jacobandrewsky/five-design-patterns-to-know-in-nodejs-265h


共有 0 則留言