I am Charmie

メモとログ

デザインパターン (C++): Factory Method

  • Creational design pattern
  • 複数クラスのインスタンスを切り替える(参照先をファイルにしたりDBにしたり)ときに使う
  • 利用者側のコード変更を最小限に留めることが目的なのかな
  • 2種類の抽象クラス
    • Productクラス: ファクトリが生成するオブジェクトのインターフェース
    • Creatorクラス: Product型のオブジェクトを返すファクトリメソッドを持つクラス
  • 2種類の
    • ConcreteProductクラス: 実際に生成されるオブジェクト
    • ConcreteCreatorクラス: ファクトリメソッドの使用者
  • 使用者はConcreteCreator型オブジェクトの持つcreate()を使ってProduct型のポインタを受け取る
  • ConcreteProduct型ではなくProduct型のポインタとして受け取ることで,使用者はサブクラスの存在を意識する必要がなくなる

header

/*** Abstract classes ***/
class Product {
public:
  virtual int anOperation() = 0;
};

class Creator {
public:
  virtual Product* create() = 0;
};

/*** Concrete classes for index 0 ***/
class ConcreteProduct0 : public Product {
public:
  ConcreteProduct0();
  int anOperation() override;
};

class ConcreteCreator0 : public Creator {
public:
  Product* create() override;
};

/*** Concrete classes for index 1 ***/
class ConcreteProduct1 : public Product {
public:
  ConcreteProduct1();
  int anOperation() override;
};

class ConcreteCreator1 : public Creator {
public:
  Product* create() override;
};

source

#include <iostream>

#include "FactoryMethod.hh"

ConcreteProduct0::ConcreteProduct0()
{
  std::cout << "  Constructor (ConcreteProduct0)" << std::endl;
}

int ConcreteProduct0::anOperation()
{
  std::cout << "  Operation (ConcreteProduct0)" << std::endl;
  return 0;
}

Product* ConcreteCreator0::create()
{
  return new ConcreteProduct0();
}

ConcreteProduct1::ConcreteProduct1()
{
  std::cout << "  Constructor (ConcreteProduct1)" << std::endl;
}
int ConcreteProduct1::anOperation()
{
  std::cout << "  Operation (ConcreteProduct1)" << std::endl;
  return 1;
}

Product* ConcreteCreator1::create()
{
  return new ConcreteProduct1();
}

int main()
{
  {
    std::cout << "ConcreteCreator0:" << std::endl;
    auto creator{ConcreteCreator0()};
    auto product{creator.create()};
    product->anOperation();
  }

  {
    std::cout << "ConcreteCreator1:" << std::endl;
    auto creator{ConcreteCreator1()};
    auto product{creator.create()};
    product->anOperation();
  }

  return 0;
}