LoginSignup
4
9

More than 1 year has passed since last update.

JavaScriptにおけるデザインパターン1(作成系)

Last updated at Posted at 2021-06-08

デザインパターンを整理する

デザインパターンを次の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

関連記事

JavaScriptにおけるデザインパターン2(構造系)
JavaScriptにおけるデザインパターン3(振舞い系)

4
9
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
9