iT邦幫忙

2021 iThome 鐵人賽

DAY 17
0

首先,先來看看一個簡單、特殊的創造物件的模式。

In software engineering, the singleton pattern is a software design pattern that restricts the instantiation of a class to one "single" instance. This is useful when exactly one object is needed to coordinate actions across the system.

Singleton (單例模式) 限制了一個類別只能建立唯一的實例。

這是什麼意思呢?如果我們先來看看一般的類別,譬如先前的 BaseballPlayer,這裡我們稍微簡化一下,並且利用它產生兩個實例 playerA 和 playerB

class BaseballPlayer {
  constructor() {}
}

const playerA = new BaseballPlayer()
const playerB = new BaseballPlayer()

很明顯的 playerA 和 playerB 是兩個不同的東西

console.log(playerA === playerB)            // false

那麼,我們要如何讓一個類別只能建立一個唯一的實例,譬如

class BaseballPlayer {
  // do something
}

const playerA = new BaseballPlayer()
const playerB = new BaseballPlayer()

然後讓 playerA 和 playerB 都會拿到同樣的實例

console.log(playerA === playerB)            // true

在進入實作之前,先來看看這個模式想要解決什麼問題。

解決什麼問題?

集中管理

當使用者透過類別建立實例的時候,每個實例就是獨立的個體,並可以各自執行各自的行為。

但如果我們想要「集中控管」使用者使用這個工具的行為,與其讓使用者自己透過類別創造出各自新的工具,不如就想辦法讓使用者每次透過類別取得實例的時候,都取得「同一個工具」,也就會使用同一個工具。

對我們來說,我們只要控制這一個工具(實例),就等於控制了所有使用者手上的工具。

共享全域變數

另一方面,如果有一個變數是需要讓所有實例共享的的話,那麼也可以透過這個方式,讓每一位使用者能夠藉由取得同一個實例來操作同一個變數。

使用場景

在系統當中,有些功能是高度共享的,如果這時候採用單例模式,就會便於管理。譬如 logger 或是 cache,不管是誰呼叫了這些實例或功能,都被集中管理,以避免不同實例各自操作所可能產生的 concurrent 問題

實作方式

要實作單例模式,有一些不同的方法,這裡使用「靜態類別」的方法來實作。

靜態類別的特性是,可以不用建立實例就可以取用其方法。所以這裡我們利用這個特性,不讓使用者建立實例 (e.g., new Gov()),而是直接呼叫靜態方法 getInstance 來取得實例。

所以在下面的程式碼當中,如果使用者呼叫了 getInstance 但此時還沒有任何實例,那麼就在這個方法內部建立新的實例。但如果實例已經存在,那麼就直接回傳該實例。

class Gov {
  private static instance: Gov

  private constructor() { }

  public static getInstance(): Gov {
    if (!Gov.instance) {
        Gov.instance = new Gov()
    }

    return Gov.instance
  }
}

如此一來,就可以確保所有使用這個類別的使用者,都可以拿到同一個實例

const yourGov = Gov.getInstance()
const myGov = Gov.getInstance()

console.log(yourGov === myGov)        // true

優點與缺點

單例模式的優點是,藉由提供所有使用者同樣的實例,讓我們可以集中管理資料、操作行為。

但是缺點是,它違反了單一功能原則,因為他控制了

  • 確保只有一個實例的產生,以及
  • 實例的實作

也因為集中管理,導致擴展性不佳。如果有任何的新需求進入,都必須更改這個類別當中的實作方式。另一方面,也可能會隱藏了它與其他類別的關係,因為對於使用者來說,只要直接取用實例就行,但如果要理解功能是如何實作,就必須進入這個類別的程式碼查看,無法透過相對外顯的繼承、參數傳遞等方式來更快理解。


上一篇
回顧 SOLID 設計原則
下一篇
Factory 工廠模式
系列文
幫自己搞懂物件導向和設計模式30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言