Facadeパターン(ファサード・パターン)は、複雑に絡み合った複数のサブシステムに対して、統一されたシンプルなインターフェース(窓口)を提供する構造デザインパターンです。これにより、クライアントは内部の各サブシステムの詳細を意識することなく、容易に機能を利用できるようになります。
課題の背景
例えば、食事をするという行為一つをとっても、その裏側では「食材の仕入れ」「調理」「配膳」「後片付け」といった複数のプロセスが存在します。もしこれらを利用者が個別に管理しなければならない場合、処理の順序や依存関係をすべて把握する必要があり、コードの複雑化と結合度の上昇を招きます。
以下は、クライアントが各作業クラスを直接操作している例です。
// 食材業者
class IngredientSupplier {
void supply() {
System.out.println("食材を仕入れる");
}
}
// 料理人
class Chef {
void cook() {
System.out.println("料理を作る");
}
}
// クライアント
public class Customer {
public static void main(String[] args) {
// クライアントが各サブシステムの処理順序を把握し、実行する必要がある
IngredientSupplier supplier = new IngredientSupplier();
supplier.supply();
Chef chef = new Chef();
chef.cook();
System.out.println("食事をする");
System.out.println("片付ける");
}
}この実装では、クライアントが具体的な作業フローに深く依存しており、プロセスが変更になった場合にクライアント側のコード修正も必要になります。
Facadeパターンの適用
そこで、各サブシステムの連携を一手に引き受ける「Facade(窓口)」クラスを導入します。Facadeクラスが内部の複雑な処理をカプセル化し、クライアントにはシンプルなメソッドのみを公開します。
public class RestaurantFacade {
private IngredientSupplier supplier;
private Chef chef;
private Waiter waiter;
private Cleaner cleaner;
public RestaurantFacade() {
// サブシステムの初期化と連携準備
this.supplier = new IngredientSupplier();
this.chef = new Chef();
this.waiter = new Waiter();
this.cleaner = new Cleaner();
// 事前準備(仕入れ)
supplier.supply();
}
// 外部に公開する統一インターフェース
public void serveDinner() {
chef.cook();
waiter.serve();
System.out.println("お客様が食事を楽しむ");
cleaner.cleanUp();
}
}このように実装することで、クライアントは単にRestaurantFacadeのserveDinnerメソッドを呼び出すだけで、一連の食事プロセスを完了できます。
public class Customer {
public static void main(String[] args) {
RestaurantFacade facade = new RestaurantFacade();
// 窓口を通じて処理を実行
facade.serveDinner();
}
}Facadeパターンは、ソフトウェアの各モジュールがそれぞれの責務に集中できるよう、適切な分工を行うための仕組みを提供します。これにより、クライアントとサブシステム間の結合度を低減し、システム全体の可読性と保守性を向上させることが可能です。