SwiftでFactory Methodパターン

Swiftデザインパターンの勉強をしています。参考書としては有名なGoF本をJava言語で説明している以下の本です。

増補改訂版Java言語で学ぶデザインパターン入門

増補改訂版Java言語で学ぶデザインパターン入門

その中で、Factory MethodパターンをSwiftで書いてみました。

Factory Patternについて

まず、Factory Methodパターンについてですが、簡単に言うとあるクラスのインスタンスの生成を、クラスに依存しない別のクラスに任す、といった感じです。

インスタンスの生成を任すクラスをFactoryクラス、そのFactoryクラスから生成するインスタンスの型をProductとして抽象的に定義しておいて、それらのクラスを継承した具体的なクラスからインスタンスを生成する流れとなります。

今回は、例としてComputerクラスを具体的なクラスとして定義します。

  • Computerクラス : Productクラスを継承した具体的なクラス。
  • ComputerFactoryクラス : Factoryクラスを継承した具体的なクラス。

実際にコードを書いてみる

では、実際に書いてみます。 Java言語では抽象クラス(メソッド)を定義できますが、Swiftでは定義できないので、似たような形で書いています。

//Factoryクラス

class Factory {
    
  func create(owner: String) -> Product {
    var p: Product = createProduct(owner)
    registerProduct(p)
    return p
  }

  func createProduct(owner: String) -> Product {
    fatalError("must be overridden")
  }

  func registerProduct(product: Product) {
    fatalError("must be overridden")
  }

}
//Productクラス

class Product {

  // 具体的な処理はサブクラスで実装する.
  func use() {
    fatalError("must be overridden")
  }

}

上記のクラスを継承した具体的なクラスを定義します。

// Computerクラス

class Computer: Product {
  let owner: String

  init(owner: String) {
    println("\(owner)のコンピュータを製造します")
    self.owner = owner
  }

  //具体的な処理の実装
  override func use() {
    println("\(self.owner)のコンピュータを使います")
  }

}
//ComputerFactoryクラス

class ComputerFactory: Factory {

  var owners = [String]()
  
  //Factoryクラスで定義した関数をオーバーライド
  override func createProduct(owner: String) -> Product {
    return Computer(owner: owner)
  }

  override func registerProduct(product: Product) {
    owners.append((product as! Computer).owner)
  }

}

実行してみます。

  var factory = ComputerFactory()
  var computer1 = factory.create("sato")  // "satoのコンピュータを製造します"
  var computer2 = factory.create("daisuke")  //"daisukeのコンピュータを製造します"
  
  computer1.use()  // => "satoのコンピュータを使います"
  computer2.use()  // => "daisukeのコンピュータを使います"

上記のようにして、具体的なクラス(ここではComputerクラス)のインスタンスをFactoryクラスを継承したComputerFactoryクラスから生成することができました。

このFactory Methodパターンのメリットとしては、Factoryクラス、Productクラス共に具体的なクラスに依存しないことが挙げられます。具体的なクラスに依存しない、汎用的なクラスにすることで同じような処理が必要な場合に再利用できるようになります。