許多 Javascript 開發者努力編寫可讀性高、維護性高且復用性高的 Javascript 代碼,因為要寫出糟糕的 Javascript 代碼非常簡單。設計模型幫助我們結構與組織我們的 Javascript 代碼。每個設計模型都包含許多特性,了解各個設計模型能幫助我們寫出優雅的程式代碼。
設計模型是被驗證過的,它已經事先幫解決一些我們可能會遇到的問題。
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 利用函數閉包(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 的目的是建立物件,對於建立相似物件的工作,我們可以使用 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)
將物件限制為整個應用程式的單一實例
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)