Skip to content

Instantly share code, notes, and snippets.

@ywwwtseng
Last active January 23, 2019 02:36
Show Gist options
  • Save ywwwtseng/b4e0fda9f045fdc27e25b5cbe8954dd3 to your computer and use it in GitHub Desktop.
Save ywwwtseng/b4e0fda9f045fdc27e25b5cbe8954dd3 to your computer and use it in GitHub Desktop.
design pattern for javascript

Javascript 設計模型

許多 Javascript 開發者努力編寫可讀性高、維護性高且復用性高的 Javascript 代碼,因為要寫出糟糕的 Javascript 代碼非常簡單。設計模型幫助我們結構與組織我們的 Javascript 代碼。每個設計模型都包含許多特性,了解各個設計模型能幫助我們寫出優雅的程式代碼。

設計模型是被驗證過的,它已經事先幫解決一些我們可能會遇到的問題。

Constructor Pattern

Gang of Four(有關於設計模型的書) 一書中沒有提及 Constructor Pattern,但我們在 Javascript 中建立一個新的物件時,Constructor Pattern 是很重要的概念。

在 Javascript 需要使用 new 操作符來創建自定義物件,new 操作符必須放在 constructor 函式前面。

語法

new constructor[([arguments])]

當 constructor 函式被執行時,必須知道四件事情

  • 建立一個全新的物件
  • 連接物件與物件原型 prototype
  • 將 constructor 函式中的 this 與被建立的物件做綁定
  • constructor 函式回傳 this

範例

function Person(name) {
  this.name = name
}

Person.prototype = {
  sayHi: function() {
    return 'hi'
  }
}

var yw = new Person('yiwei')
yw.sayHi()

我們可以使用 ES6 Class 的寫法,讓程式看起來像 class-based 的語言,它最終會被編譯成 prototype

class Person {
  constructor(name) {
    this.name = name
  }
  
  sayHi() {
    return 'hi'
  }
}

var yw = new Person('yiwei')
yw.sayHi()

Module Pattern

Module Pattern 利用函數閉包(closure)的特性進行封裝,避免污染 Global,將方法和變數限制在一個範圍內存取與使用,也將實作隱藏起來,只提供公開的介面(public API)。我們可以使用 Module Pattern 實作服務(database calls, HTTP calls)

function StudentModule() {
  // private
  var db = {}
  
  // public
  return {
    get: function(id) {
      if (!id) return
      console.log(`Getting Student ${id} from db`)
    
      return {name: 'yiwei', school: 'NSYSU'}
    },
    
    save: function(student) {
      console.log(`Saving  ${student.name} to the db`)
    }
  }
}

var studentModule = StudentModule()
studentModule.get(1)

Factory Pattern

Factory 的目的是建立物件,對於建立相似物件的工作,我們可以使用 Factory Pattern 來達到程式碼的精簡,提供一個無需事先知道明確型別建立物件的方式。

由 Factory 所建立的物件,會被設計成繼承同一個父物件

function Employee(options) {
  this.id = options.id || '-9999999999'
  this.firstname = options.firstname || 'no first name'
  this.lastname = options.lastname || 'no last name'
  this.yearBonus = options.yearBonus || 200000
}

function Clerk(options) {
  Employee.call(this, options)
}
Clerk.prototype = Object.create(Employee.prototype)
Clerk.prototype.construtor = Clerk

function Manager(options) {
  Employee.call(this, options)
}
Manager.prototype = Object.create(Employee.prototype)
Manager.prototype.construtor = Manager

function Teacher(options) {
  Employee.call(this, options)
}
Teacher.prototype = Object.create(Employee.prototype)
Teacher.prototype.construtor = Teacher

function EmployeesFactory() {}
EmployeesFactory.prototype.createEmployee = function(options) {
  switch (options.employeeType) {
    case 'Clerk':
      return new Clerk(options)
    case 'Manager':
      return new Manager(options)
    case 'Teacher':
      return new Teacher(options)
    default:
      return
  }
}

var factory = new EmployeesFactory()

var person = factory.createEmployee({
  employeeType: 'Teacher',
  id: 234234,
  firstname: 'tseng',
  lastname: 'yiwei',
  yearBonus = 200000
})

console.log(person instanceof Teacher)

Singleton Pattern

將物件限制為整個應用程式的單一實例

var store = (function () {
  var state
  
  function createState() {
    var state = new Object('state')
    
    return state
  }
  
  return {
    getState: function() {
      if (!state) state = createState()
      
      return state
    }
  }
})()

var state1 = store.getState()
var state2 = store.getState()

console.log(state1 === state2)

參考

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment