天天看點

JavaScript中的五大設計模式

JavaScript中的五大設計模式

設計模式是我大學教育中的一個亮點。當時,我沒有完全了解它們的重要性,但随着我在開發人員職業生涯中的積累,我開始欣賞它們在軟體開發中的關鍵作用。這些模式為開發人員在複雜項目上交流和協作提供了通用語言。它們是以可擴充和可維護的方式解決反複出現的問題的解決方案。

它們是任何有經驗的開發人員的必要工具,并繼續影響我在日常工作中處理和解決問題的方式。在文章中,我将介紹作為一個JavaScript開發者,你應該知道的5種設計模式。讓我們來解鎖JavaScript設計模式的力量。

1-工廠模式

工廠模式是一種設計模式,它提供了一種建立對象的方法,而無需指定要建立的對象的确切類。工廠類或方法用于根據特定的條件或輸入來确定要執行個體化的對象類。這種方法允許更靈活和可維護的代碼,因為對象的建立可以集中并從其餘代碼中抽象出來。

想象一下,你正在iOS和Android上建構一個跨平台應用程式。這個應用程式在兩個平台上都有相同的界面,但你的代碼包含了很多條件檢查,以确定顯示哪個按鈕。

let button =
  platform == 'ios' ? 
  new IOSButton('Submit') 
  : new AndroidButton('Submit');           

這不是很容易維護。讓我們以工廠模式來更好的完成此操作:

class IOSButton {
  constructor(text) {
    this.text = text;
  }
}

class AndroidButton {
  constructor(text) {
    this.text = text;
  }
}

class ButtonFactory {
  createButton(text, platform) {
    switch (platform) {
      case 'ios':
        return new IOSButton(text);
      case 'android':
        return new AndroidButton(text);
      default:
        throw new Error('Invalid platform');
    }
  }
}

const buttonFactory = new ButtonFactory();
// Create an IOS button
const iosButton = buttonFactory.createButton('Submit', 'ios');
// Create an Android button
const androidButton = buttonFactory.createButton('Submit', 'android');           

在這個例子中,我們有兩個類,IOSButton和AndroidButton。我們還有一個ButtonFactory類,它有一個createButton方法,它接受一個text和一個platform參數,并根據platform傳回一個新的button對象。createButton方法使用switch語句來根據平台執行個體化哪個按鈕類。

2-單例模式

單例設計模式是一個強大的軟體設計原則,它確定一個類隻能有一個執行個體,同時提供對該執行個體的全局通路點。在某些情況下,應該隻存在一個類執行個體并強制執行限制。緩存、線程池和系統資料庫應該隻有一個執行個體。

通常,類的構造函數被設定為private,以確定隻有類成員可以通路和執行個體化它,進而確定整個應用程式隻有一個類執行個體。

JavaScript沒有私有構造函數的概念,是以達到相同效果的最常見方式是使用閉包和立即調用函數表達式(IIFE):

const Singleton = (function () {
  let instance;

  function Person(firstName, lastName) {
    this.firstName = firstName;
    this.lastName = lastName;
  }

  function createInstance() {
    // 這是建立單例對象的地方
    const person = new Person('Rabi', 'Siddique');
    return person;
  }

  return {
    getInstance: function () {
      if (!instance) {
        instance = createInstance();
      }
      return instance;
    },
  };
})();

const instance1 = Singleton.getInstance();
const instance2 = Singleton.getInstance();
console.log(instance1 === instance2); // true           

3-原型模式

原型模式通過複制已存在的對象(稱為原型)來建立新對象。

原型模式是一種強大的技術,可以通過減少建立新對象所需的時間和資源來提高建立對象的性能,特别是當對象有很多字段或需要大量初始化處理(例如從資料庫擷取資料、調用API或執行複雜計算)時。該模式建立一個原型對象作為新對象的藍圖,進而消除了進一步記憶體配置設定和初始化的需要。通過複制原型對象來建立新對象,可以大大加快對象建立過程。

此外,原型模式提供了繼承的另一種方式,允許對象從現有對象繼承功能,而不需要複雜的類層次結構,使代碼庫更易于維護和了解。讓我們看一個例子:

function Person(firstName, lastName) {
  this.firstName = firstName;
  this.lastName = lastName;
}

const person1 = new Person('Rabi', 'Siddique');
const person2 = Object.create(person1);

console.log(`${person2.firstName} ${person2.lastName}`); // Rabi Siddique           

在這個例子中,我們通過Object.create方法複制person1的原型建立了一個新對象person2。person2将繼承person1的屬性和方法(如果有的話)。

4-代理模式

代理的字面定義是代表他人的權力。在代理模式設定中,代理在用戶端面前代表另一個對象,稱為主體。真正的主體被屏蔽,無法直接與用戶端互動。這在很多情況下都很有用,例如:

  • 通路位于另一台計算機或另一個位址空間中的遠端對象。
  • 保護主體不被未經授權的客戶通路。
  • 将昂貴對象的建立推遲到需要時。
  • 将查詢結果緩存到主題,以便用戶端更快地通路。

一個代理模式的JavaScript例子:

// 原對象
const person = {
  name: 'Rabi Siddique',
  city: 'Gujranwala',
};

// The proxy object
const personProxy = new Proxy(person, {
  get: function (target, property) {
    return target[property];
  },
  set: function (target, property, value) {
    target[property] = value;
  },
});

// 使用proxy通路原始對象的屬性
console.log(personProxy.name); // 'Rabi Siddique'

// 使用proxy修改原始對象的屬性
personProxy.city = 'Lahore';
console.log(personProxy.city); // 'Lahore'           

在這個例子中,personProxy是一個封裝了原始person對象的代理對象。當通過personProxy通路或修改person對象的屬性時,會調用代理的get和set方法。

5-建構者模式

建構者模式是一種有用的設計模式,它簡化了建立複雜對象的過程。它允許您将對象的表示與其構造分離,使使用相同的構造過程更容易建立不同的表示。

假設你有一個熱狗攤,客戶需要在構造函數中告訴你他們想要的所有東西。這很難跟蹤所有的選項,有時我們可能希望将每個步驟推遲到稍後的一點。在建構者模式中,我們使用方法而不是構造器逐漸建立對象。這允許更多的靈活性和更好的組織。

在Javascript中,我們可以使用this關鍵字在每個方法中引用目前對象執行個體,并實作方法鍊。這意味着我們可以執行個體化一個對象,然後将方法連結到它,始終将對象作為傳回值。這使得建構複雜對象的過程更加高效和易于管理。

class HotDogBuilder {
  constructor() {
    this.hotDog = {};
  }

  addBun(bun) {
    this.hotDog.bun = bun;
    return this;
  }

  addSausage(sausage) {
    this.hotDog.sausage = sausage;
    return this;
  }

  addToppings(toppings) {
    this.hotDog.toppings = toppings;
    return this;
  }

  addSauces(sauces) {
    this.hotDog.sauces = sauces;
    return this;
  }

  build() {
    return this.hotDog;
  }
}

const hotDog = new HotDogBuilder()
  .addBun('sesame')
  .addSausage('beef')
  .addToppings(['onion', 'tomato'])
  .addSauces(['mustard', 'ketchup'])
  .build();

console.log(hotDog);           

在我們的示例中,我們可以使用建構器模式,通過有組織且高效地添加不同的配料、醬料和調味品,建立不同的熱狗變體。建構者模式允許我們将建構邏輯委托給一個完全不同的類,這使得建構過程更加靈活。

感謝您的閱讀。我希望這篇文章對你有所幫助。如果你還有任何問題,請聯系我們。我很樂意幫忙。

繼續閱讀