見出し画像

🛠️Builderパターンは棟梁系のだんどり系で職人技

「こんな感じ」をサブクラスと一緒に伴走できる。Builderとパターンなら

パターン構成はほとんどStrategy/Bridge/Stateと同じ、違うのは心意気

カスタマイズしやすく、サブクラスを急速に増やすファクトリメソッドを用いるところから出発し、一層の柔軟性が必要となる箇所が発見されるに伴いより柔軟だが複雑なAbstract Factory→PrototypeBuilderへと発達してゆく

Builderパターンだが構成はほぼStrategyとかと一緒 右下に具体パターンがあって上で抽象

段階的にオブジェクトの製造過程を指示できるのがビルダーパターンのいいところ

一発で製品を構築するクリエイティブパターンとは異なり、ビルダーパターンは、ディレクターのコントロールのもと、段階的に製品を構築していきます。(略)これにより、構築プロセス、ひいては出来上がった製品の内部構造をより細かく制御することができます。

https://amzn.to/3J40y2R

サンプルコードで紹介する迷路の例では、MazeBuilderインターフェイスを使って、既存の部屋の間にドアを追加することができます。ボトムアップで構築される解析木のような木構造もその一例である。この場合、ビルダーは子ノードをディレクターに返し、ディレクターは子ノードをビルダーに戻して親ノードを構築する。

https://amzn.to/3J40y2R


ファクトリとの差分からビルダーの本質を考えてみよう。

Abstract Factoryは、複雑なオブジェクトを構築できるという点で Builder に似ています。主な違いは、Builder パターンが複雑なオブジェクトを段階的に構築することに焦点を当てている点です。Abstract Factoryの強調事項は、製品オブジェクトのファミリーにあります。(単純、複雑にかかわらず)

注文製造なのがAbstract Factory

ビルダーは最終段階として製品オブジェクトを返しますが、Abstract Factoryはすぐに製品オブジェクトを返します

ツールキットの例で

抽象クラス(アブストラクトファクトリ)を通して各ファクトリがクリエートするのに注目

抽象クラスを通して、(concreteFactoryが)クリエートするから、抽象クラスの変更をしたら、全部変えなければならない制約が出てくる。

https://amzn.to/3ACWhRI

Abstract FactoryのCreate部分はFactoryMethodかPrototypeと併用

依存度を下げたいとき、数が多いときにPrototypeを使う
さらにFactoryMethodは二つの実装方法(と2つ実際の利用方法)がある

  1. Creatorが抽象クラス(FactoryMethod側に方針を示さない)

  2. Creatorが具象クラス(FactoryMethodの基本処理はCreator側に書いてある)

  3. Creatorを介さずにもとのFactoryMethodを使う

  4. 引数などに応じて一つのFactoryMethodが複数のProductを作る

Prototypeの場合は初期化(Initialize)が入るが、FactoryMethodは初期化が不要。このあたりで使い方が分かれてくる。

ファクトリーメソッドは、通常、テンプレートメソッドの中で呼び出される。

Interviewsでは、AbstractFactoryクラスを表すために "Kit "というサフィックスを使用しています。

https://stuff.mit.edu/afs/sipb/project/interviews/man/refman.PS

例えばRTF(リッチファイルフォーマット)から別のファイルを出力するコンバーターを作ると仮定したときに、異なるフォーマットを作りだすコンバーターの祖型をビルダーと呼ぶ。共通した処理は祖型に書いてバリエーションの組み立てを棟梁(ディレクター)が管理するという座組。

DoxygenとJavadocのちがいで考えてみる

DOXYGENはBuilder的な発想で構築されている

JAVADOCはBuilderで組まなくても、factoryMethodでいい。

壮大かつ選択可能ならビルダー、一意でバリエーションがあるならファクトリメソッドと考えてみる

function run() {
   var shop = new Shop();
   var carBuilder = new CarBuilder();
   var truckBuilder = new TruckBuilder();
   var car = shop.construct(carBuilder);
   var truck = shop.construct(truckBuilder);
   car.say();
   truck.say();
   log.show();
}
function run() {
   var persons = [];
   var employeeFactory = new EmployeeFactory();
   var vendorFactory = new VendorFactory();
   persons.push(employeeFactory.create("Joan DiSilva"));
   persons.push(employeeFactory.create("Tim O'Neill"));
   persons.push(vendorFactory.create("Gerald Watson"));
   persons.push(vendorFactory.create("Nicole McNight"));
   for (var i = 0, len = persons.length; i < len; i++) {
       persons[i].say();
   }
   log.show();
}

ファクトリーが気にするのはAssembleされ統制の効いた製品群である

function run() {
   var employees = [];
   var factory = new Factory();
   employees.push(factory.createEmployee("fulltime"));
   employees.push(factory.createEmployee("parttime"));
   employees.push(factory.createEmployee("temporary"));
   employees.push(factory.createEmployee("contractor"));
   
   for (var i = 0, len = employees.length; i < len; i++) {
       employees[i].say();
   }
   log.show();
}

何が製造されるか決まっているのがファクトリーメソッド(create)

function run() {
   var proto = new Customer("n/a", "n/a", "pending");
   var prototype = new CustomerPrototype(proto);
   var customer = prototype.clone();
   customer.say();
}






お願い致します