---
# System prepended metadata

title: 'CH 11: Conventional Module & Singleton Class'
tags: [clean code]

---

# CH 11: Conventional Module & Singleton Class
###### tags: `clean code`

## Coventional Module
* **用物件字面值提供方法集合的一個方式**
* 以型別來看，就是個普通的物件
* 可引入其他外部函式 -> 增加靈活性但同時也要考慮可維護性


什麼是物件字面值
* JS ES6 語法
* 在物件內宣告函式可以省略 function
```
const obj = {
  foo: function(a) {
    console.log(a);
  },
};

const obj = {
  foo(a) {
    console.log(a);
  },
};
```

***Coventional Module Example***
```=javascript
const catchError = ()=>{console.log(error)}

const todoListUtils = {
    setInit(config){ // 初始化
        this.config=config
    },
    addNew(thing, date){},
    removeOne(thing, date){},
    completeOne(id){},
    
    catchError, // 引入外部函式
}

todoListUtils.addNew()
todoListUtils.catchError()

```

#### Coventional Module 使用時機
集合一組相關的方法，包裝成具有通用名稱的特性。（我想就是可以被全局引用，例如書上給的 log 例子）

----

## Singleton Class (書中)
* 不需要繼承和實例化的常規 OOP 類別
* 用簡單的建構函數定義初始化 new class + constructor()
* 用常規方式定義私有變數及公有方法

! 關於書中的例子，沒查到這種寫法的正確性

## Singleton Class 單例模式(補充)
* 限制每個實例化後的實例都是同一個（指向同個物件），也就是僅有一個實例
* 僅有自己可以生成實例
* 提供全局可訪問的 method
* 目的：性能、安全

***Singleton Class Example***
* JS
```=javascript
class Logger {
  success(message) {
    console.log(`SUCCESS: ${message}`)
  }

  error(message) {
    console.error(`ERROR: ${message}`)
  }
}

class SingletonLogger {
  static _instance

  static _createInstance() {
    const logger = new Logger()
    return logger
  }

  static getInstance() { // 特殊處理，每個 obj 都是同一個
    if (!this._instance) {
      this._instance = this._createInstance()
    }

    return this._instance
  }
}

const instance1 = SingletonLogger.getInstance()
const instance2 = SingletonLogger.getInstance()

console.log(instance1 === instance2)
// => true
```

* node.js
```=javascript
class Logger {
  constructor() {
    this.log = [];
  }

  get log() {
    return this.log;
  }

  get count() {
    return this.log.length;
  }

  store(result) {
    this.log.push(result);
  }

  log(result) {
    console.log(result);
    this.store(result);
  }

	module.exports = new Logger(); // key point
}
```
* module.exports 僅 node.js 支持
* 當我們執行上面這個 file 時，會實例化一個 Logger 並存在 cache，node.js 會將同一個實例輸出到每個引用 Logger 的 file 裡
* 在後端的設計裡，[單例還有多種模式](http://wuchong.me/blog/2014/08/28/how-to-correctly-write-singleton-pattern/)


## Ending
恭喜大家從 clean code 解脫 ：）！ ✿✿ヽ(ﾟ▽ﾟ)ノ✿✿✿ヽ(ﾟ▽ﾟ)ノ✿ 請給自己一個掌聲 %%%%%
一起邁入下一個20週年紀念版的磨練

（請原諒覺得書裡結尾稍微無聊的我並不想要重複敘述一遍）

參考
https://blog.husamajour.dev/nodejs-design-patterns-or-singleton-pattern
http://wuchong.me/blog/2014/08/28/how-to-correctly-write-singleton-pattern/