デザインパターンを整理する
デザインパターンを次の3つに分けて考えます
- 作成系デザインパターン (コンストラクター、ファクトリー、シングルトンなど)
- 構造系デザインパターン (デコレータ、ファサードなど)
- 振舞い系デザインパターン (メディエータ、オブザーバーなど)
作成系デザインパターン
簡単にいうと、オブジェクト作成メカニズムを扱うデザインパターンであり、状況に即した方法でオブジェクトを作成しようとするもの。
コンストラクターパターン
Learning JavaScript Design Patternsより
コンストラクターは、メモリが割り当てられた後、新しく作成されたオブジェクトを初期化するために使用される特別なメソッドです。
function Person(first, last) {
this.first = first
this.last = last
this.greet = function () {
console.log('こんにちは、' + this.last + this.first + 'です。')
}
}
let person = new Person('太郎', '山田')
let person2 = new Person('次郎', '鈴木')
person.greet() // こんにちは、山田太郎です。
person2.greet() // こんにちは、鈴木次郎です。
この実装には問題があります。
他の開発者が同じソースコード内のどこかで新たな関数を追加すると下記のように変更されてしまう可能性があります。
person.greet = function () {
console.log('さようなら!')
}
person.greet() // さようなら
person2.greet() // こんにちは、鈴木次郎です。
同じメソッドならばどのオブジェクトに対しても同じように機能する必要があります。
そのためコンストラクター内で定義せず、コンストラクターの外で、プロトタイプというプロパティーに定義する必要があります。
function Person(first, last) {
this.first = first
this.last = last
// this.greet = function () {
// console.log('こんにちは、' + this.last + this.first + 'です。')
// }
}
Person.prototype.greet = function () {
console.log('こんにちは、' + this.last + this.first + 'です。')
}
let person = new Person('太郎', '山田')
let person2 = new Person('次郎', '鈴木')
person.greet()
person2.greet()
ファクトリーパターン
Learning JavaScript Design Patternsより
ファクトリ パターンは、オブジェクトを作成するという概念に関係するもう 1 つの作成パターンです。カテゴリ内の他のパターンと異なる点は、コンストラクターを使用する必要がないことです。代わりに、ファクトリはオブジェクトを作成するためのジェネリック インターフェイスを提供でき、作成するファクトリ オブジェクトのタイプを指定できます。
// https://github.com/pkellz/devsage/blob/master/DesignPatterns/FactoryDesignPattern.js より
function Developer(name)
{
this.name = name
this.type = "Developer"
}
function Tester(name)
{
this.name = name
this.type = "Tester"
}
function EmployeeFactory()
{
this.create = (name, type) => {
switch(type)
{
case 1:
return new Developer(name)
case 2:
return new Tester(name)
}
}
}
function say()
{
console.log("Hi, I am " + this.name + " and I am a " + this.type)
}
const employeeFactory = new EmployeeFactory()
const employees = []
employees.push(employeeFactory.create("Patrick", 1))
employees.push(employeeFactory.create("John", 2))
employees.push(employeeFactory.create("Jamie", 1))
employees.push(employeeFactory.create("Taylor", 1))
employees.push(employeeFactory.create("Tim", 2))
employees.forEach( emp => {
say.call(emp)
})
// 結果
// Hi, I am Patrick and I am a Developer
// Hi, I am John and I am a Tester
// Hi, I am Jamie and I am a Developer
// Hi, I am Taylor and I am a Developer
// Hi, I am Tim and I am a Tester
このようにname、typeの違う複数のobjectを作成し利用する場合に、
employeeFactory.create(name, type)
の一行を追加するだけで新たに追加できます。
シングルトンパターン
Learning JavaScript Design Patternsより
シングルトン パターンは、クラスのインスタンス化を単一のオブジェクトに制限する。
let instance = null
function Person(first, last) {
if (!instance) {
this.first = first
this.last = last
instance = this
} else {
return instance
}
}
let person = new Person('太郎', '山田')
let person2 = new Person('次郎', '鈴木')
console.log('person: ', person) // person: Person { first: '太郎', last: '山田' }
console.log('person2: ', person2) // person2: Person { first: '太郎', last: '山田' }
この例では2回目以降のnewがelse {return instance}
により新たなインスタンスが作成されないように制御しています。
参考文献
Learning JavaScript Design Patterns