社内勉強会用-AbstractFactoryパターン

| トラックバック(0)
現在社内勉強会ではデザインパターンが持ち回りで行われています。

とりあえず今回は社内勉強用資料として。

自分の担当はAbstractFactoryパターン。

AbstractFactory = 「抽象的な工場」・・・。

名前だけでは一体何がうれしいのかまったくわかりませんね。

デザパタ本での解説は関連する部品を組み合わせて製品を作るとなっています。

その他では・・・

インスタンスの生成を専門に行うクラスを用意することで、
整合性を必要とされる一連のオブジェクト群を間違いなく生成するパターン

「関連、または依存しあうオブジェクトのファミリを、その具象クラスを指定すること無しに生成する
インターフェースを提供する」

とか言われています。

イメージ図はこんな感じ。

abstract_factory.gif

で、クラス図で表すと下のようになります。

Untitled.png
まぁ何はともあれAbstractFactoryを使ったサンプルプログラムを見てみましょう。。
サンプルなので小さめに。
// ペットボトル工場の抽象クラス
abstract class abstractPlasticBottleFactory {
  abstract public function makeContent();
  abstract public function makeBottle();
}

// オレンジ工場(具象クラス)
class orangeFactory extends abstractPlasticBottleFactory {

  public function makeContent() {
    return new orangeContent();
  }

  public function makeBottle() {
    return new orangeBottle();
  }

}

// コーラ工場(具象クラス)
class colaFactory extends abstractPlasticBottleFactory {

  public function makeContent() {
    return new colaContent();
  }

  public function makeBottle() {
    return new colaBottle();
  }

}

// 中身の抽象クラス
abstract class Content {
  abstract public function createContent();
}

class orangeContent extends Content {

  public function createContent() {
    return 'Create Orange Juice';
  }

}

class colaContent extends Content {

  public function createContent() {
    return 'Create Cola';
  }

}

// ボトルの抽象クラス
abstract class bottle {
  abstract public function createBottle();
}

class orangeBottle extends bottle {

  public function createBottle() {
    return 'Create Orange Bottle';
  }

}

class colaBottle extends bottle {

  public function createBottle() {
    return 'Create Cola Bottle';
  }

}

// クライアントクラス
class createFactory {
  private $content=null;
  private $bottle=null;

  function __construct( abstractPlasticBottleFactory $factory ) {
    $this->content = $factory->makeContent();
    $this->bottle = $factory->makeBottle();
  }

  public function create() {
    echo $this->content->createContent() . "\n";
    echo $this->bottle->createBottle() . "\n";
  }
}

// オレンジジュース
$orange_factory = new createFactory( new orangeFactory );
$orange_factory->create();

// コーラ
$cola_factory = new createFactory( new colaFactory );
$cola_factory->create();



実行すると・・・。
Create Orange Juice
Create Orange Bottle
Create Cola
Create Cola Bottle
サンプルの例がなんかおかしい気もしますが。。

今回のサンプルでは「abstractPlasticBottleFactory」が工場の抽象クラスとなり、
「abstractPlasticBottleFactory」を継承する工場の具象クラスの実装すべきメソッドを定義しています。

工場の具象クラスでは利用すべきオブジェクト(材料)を用意し独自に実装を行えます。
工場の具象クラスで利用する各材料に関しても抽象クラスを定義して
おくことによりクライアントプログラム対してどの工場を利用するのかだけ指定すれば
一連のオブジェクト群を間違いなく生成することができます。

今回の例は「Orange」と「Cola」の2つだけですが、具象クラスを同様に増やすことで
工場のバリエーションを増やすことができます。

利用する側はどんな工場が存在するのかさえ知っていればどの工場でも
同じ呼び出し方法で利用可能です。
(※工場内で何が起きているかは知らなくても使える)

メリット
・具象クラスに処理をまとめることができる
・利用する材料の組み合わせを各工場で変更できる
・クライアントクラスが再利用可能

デメリット
・抽象クラスの工場で新たにメソッドを定義した場合に抽象クラスの工場を継承する全ての具象工場で
変更が必要になる。

要は、インスタンス化を直接行わず、工場となる関数にお任せすることです。
こうすることにより、部品となる クラスのインスタンス化が、ソースコードの中に
散在しなくなるため、変更が容易になります。
一度工場を作ってしまえ ば、後は全ての操作がインタフェースクラス
経由で行われる訳です。
このように、全てがインタフェースクラス経由でだけ行われるため、外部から
は、内部で何をしているかは 一切気にかける必要はなく、しかも、結果的に
どんな部品が作られようとも、同じ操作ができます。
また、1つの工場で作成される部品のセットは、常に同じものなので、複数の部品を
常に正しい組み合わせ で生成できます。
Abstract Factoryパターンでは、このような間違った組み合わせが起こり得ません。 
部品を作るのは工場の内部であり、外部からはその工場を直接触らない
(=インタフェースしか触れない)ためです。

で、↑のデメリットに対して抽象クラスの工場でデフォルトの指定をしておけばいいじゃないか?
という意見もあります。。
確かにそうすれば全ての具象クラスで処理を追加する必要も無くなる。
でもそれって工場の種類が増えた場合に、具象クラスでメソッドの実装を忘れたら
意図しない結果が返ってくる可能性もあるのではなかろうか?
材料の組み合わせを各具象クラスが責任を持って指定していないのだから。。
そのときの要件によってどっちがいいのか変わるようなきがする・・・。


ギコ猫とAbstract Factoryパターン













トラックバック(0)

トラックバックURL: http://www.mogumagu.com/mt/mt-tb.cgi/27

2012年1月

1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30 31        

ウェブページ

このブログ記事について

このページは、モグマグが2010年6月20日 00:25に書いたブログ記事です。

ひとつ前のブログ記事は「ThinkPad x61にFedora13入れるメモ」です。

次のブログ記事は「社内勉強会用-Flyweightパターン」です。

最近のコンテンツはインデックスページで見られます。過去に書かれたものはアーカイブのページで見られます。

Powered by Movable Type 5.01