ビルダーパターン

ビルダーパターンは作成型デザインパターンの一つで、複雑なオブジェクトを作成する手順と表現方法を分離できるようにします。

ビルダーパターンは作成型デザインパターンの一つで、その主な目的は、複雑なオブジェクトの構築プロセスとその表現を分離し、異なる表現形式を持つオブジェクトを作成できるようにすることです。

概要

意図

複雑な構築プロセスとその表現を分離し、同じ構築プロセスで異なる表現を作成できるようにします。

主な解決

ソフトウェアシステムでは、複雑なオブジェクトの作成は通常、複数の部分で構成されます。これらの部分の組み合わせは頻繁に変化しますが、組み合わせのアルゴリズムは比較的安定しています。

使用するタイミング

一部の基本部品は変わらないが、その組み合わせが頻繁に変化する場合。

解決方法

変化する部分と変化しない部分を分離します。

キーコード

  • ビルダー:インスタンスを作成して提供します。
  • ディレクター:構築されたインスタンスの依存関係を管理し、構築プロセスを制御します。

適用例

  • ケンタッキーを例にとると、ハンバーガー、コーラ、フライドポテト、フライドチキンなどは変わりませんが、その組み合わせは頻繁に変化し、さまざまな「セット」が生成されます。
  • Java におけるStringBuilder。

長所

  • 構築プロセスと表現を分離することで、構築プロセスがより柔軟になり、異なる表現を構築できます。
  • 構築プロセスをより適切に制御でき、具体的な構築の詳細を隠すことができます。
  • コードの再利用性が高く、異なる構築プロセスで同じビルダーを再利用できます。

短所

  • 製品の属性が少ない場合、ビルダーパターンはコードの冗長性を引き起こす可能性があります。
  • システムのクラスとオブジェクトの数が増加します。

使用シーン

  • 生成するオブジェクトが複雑な内部構造を持つ場合。
  • 生成するオブジェクトの内部属性が相互に依存している場合。

注意事項

ファクトリーパターンとの違いは、ビルダーパターンが部品の組み立て順序により重点を置いていることです。

構造

ビルダーパターンには、以下の主要な役割が含まれます:

  • プロダクト(Product):構築する複雑なオブジェクト。プロダクトクラスには通常、複数の部分または属性が含まれます。

  • 抽象ビルダー(Builder):製品を構築するための抽象インターフェースを定義し、製品の各部分を構築するメソッドを含みます。

  • 具体ビルダー(Concrete Builder):抽象ビルダーインターフェースを実装し、製品の各部分の構築方法を具体的に決定し、最終的に構築された製品を返す責任を負います。

  • ディレクター(Director):ビルダーのメソッドを呼び出して製品を構築する責任を負います。ディレクターは具体的な構築プロセスを理解せず、製品の構築順序と方法のみに関心を持ちます。

実装

ファーストフード店のビジネスケースを想定します。典型的なセットは、ハンバーガー(Burger)と冷たい飲み物(Cold drink)で構成されます。ハンバーガー(Burger)は、ベジバーガー(Veg Burger)またはチキンバーガー(Chicken Burger)で、紙の箱に包まれています。冷たい飲み物(Cold drink)は、コカ・コーラ(coke)またはペプシ(pepsi)で、瓶に入っています。

私たちは、食品アイテム(ハンバーガーや冷たい飲み物など)を表すItemインターフェースと、それを実装するItemエンティティクラス、および食品の包装を表すPackingインターフェースと、それを実装するPackingエンティティクラスを作成します。ハンバーガーは紙の箱に包まれ、冷たい飲み物は瓶に入っています。

次に、私たちはMealクラスを作成します。このクラスにはItemのArrayListと、を組み合わせることでItem異なるタイプのMealオブジェクトを作成するためのMealBuilder。BuilderPatternDemoクラスを使用してMealBuilderを作成しますMeal。

建造者模式的 UML 图

ステップ 1

食品アイテムと食品パッケージを表すインターフェースを作成します。

Item.java

public interface Item { public String name(); public Packing packing(); public float price(); }

Packing.java

public interface Packing { public String pack(); }

ステップ 2

Packing インターフェースを実装するエンティティクラスを作成します。

Wrapper.java

public class Wrapper implements Packing { @Override public String pack() { return "Wrapper"; } }

Bottle.java

public class Bottle implements Packing { @Override public String pack() { return "Bottle"; } }

ステップ 3

Item インターフェースを実装する抽象クラスを作成します。このクラスはデフォルトの機能を提供します。

Burger.java

public abstract class Burger implements Item { @Override public Packing packing() { return new Wrapper(); } @Override public abstract float price(); }

ColdDrink.java

public abstract class ColdDrink implements Item { @Override public Packing packing() { return new Bottle(); } @Override public abstract float price(); }

ステップ 4

Burger と ColdDrink を拡張するエンティティクラスを作成します。

VegBurger.java

public class VegBurger extends Burger { @Override public float price() { return 25.0f; } @Override public String name() { return "Veg Burger"; } }

ChickenBurger.java

public class ChickenBurger extends Burger { @Override public float price() { return 50.5f; } @Override public String name() { return "Chicken Burger"; } }

Coke.java

public class Coke extends ColdDrink { @Override public float price() { return 30.0f; } @Override public String name() { return "Coke"; } }

Pepsi.java

public class Pepsi extends ColdDrink { @Override public float price() { return 35.0f; } @Override public String name() { return "Pepsi"; } }

ステップ 5

上記で定義した Item オブジェクトを持つ Meal クラスを作成します。

Meal.java

import java.util.ArrayList; import java.util.List; public class Meal { private List<Item> items = new ArrayList<Item>(); public void addItem(Item item){ items.add(item); } public float getCost(){ float cost = 0.0f; for (Item item : items) { cost += item.price(); } return cost; } public void showItems(){ for (Item item : items) { System.out.print("Item : "+item.name()); System.out.print(", Packing : "+item.packing().pack()); System.out.println(", Price : "+item.price()); } } }

ステップ 6

MealBuilder クラスを作成します。実際のビルダークラスは Meal オブジェクトの作成を担当します。

MealBuilder.java

public class MealBuilder { public Meal prepareVegMeal (){ Meal meal = new Meal(); meal.addItem(new VegBurger()); meal.addItem(new Coke()); return meal; } public Meal prepareNonVegMeal (){ Meal meal = new Meal(); meal.addItem(new ChickenBurger()); meal.addItem(new Pepsi()); return meal; } }

ステップ 7

BuiderPatternDemo は MealBuilder を使用して、ビルダーパターン(Builder Pattern)をデモンストレーションします。

BuilderPatternDemo.java

public class BuilderPatternDemo { public static void main(String[] args) { MealBuilder mealBuilder = new MealBuilder(); Meal vegMeal = mealBuilder.prepareVegMeal(); System.out.println("Veg Meal"); vegMeal.showItems(); System.out.println("Total Cost: " +vegMeal.getCost()); Meal nonVegMeal = mealBuilder.prepareNonVegMeal(); System.out.println("\n\nNon-Veg Meal"); nonVegMeal.showItems(); System.out.println("Total Cost: " +nonVegMeal.getCost()); } }

ステップ 8

プログラムを実行し、結果を出力します:

Veg Meal
Item : Veg Burger, Packing : Wrapper, Price : 25.0
Item : Coke, Packing : Bottle, Price : 30.0
Total Cost: 55.0


Non-Veg Meal
Item : Chicken Burger, Packing : Wrapper, Price : 50.5
Item : Pepsi, Packing : Bottle, Price : 35.0
Total Cost: 85.5

関連記事

その他の拡張