ファクトリーパターン
CoddyのJavaジャーニー「オブジェクト指向プログラミング」セクションの一部。レッスン 66/87。
Factoryパターンは、オブジェクトの生成を別のmethodまたはclassに委譲する生成に関するデザインパターンです。コード内で直接newを使用する代わりに、ファクトリにオブジェクトをcreateしてもらいます。これは、共通のinterfaceまたは親を共有する、関連する複数のclassesをhaveしている場合に特に便利です。
email、SMS、または push notifications を送信できる notification system を考えてみましょう。Factory がなければ、コードはすべての concrete class について know している必要があります。
// Factoryなし - クライアントはすべての具象クラスを知る必要がある
Notification notification;
if (type.equals("email")) {
notification = new EmailNotification();
} else if (type.equals("sms")) {
notification = new SMSNotification();
}Factory Patternを使用すると、この作成ロジックを一元化できます。
public interface Notification {
void send(String message);
}
public class EmailNotification implements Notification {
public void send(String message) {
System.out.println("Email: " + message);
}
}
public class SMSNotification implements Notification {
public void send(String message) {
System.out.println("SMS: " + message);
}
}
public class NotificationFactory {
public static Notification create(String type) {
if (type.equals("email")) {
return new EmailNotification();
} else if (type.equals("sms")) {
return new SMSNotification();
}
return null;
}
}これでclient コードはよりすっきりし、concrete クラスに依存しなくなりました。
Notification notification = NotificationFactory.create("email");
notification.send("Hello!"); // 出力: Email: Hello!主な利点は、新しい notification の種類を追加する際に、factory の更新だけで済むことです。client コードは変更されません。これは interface に対してプログラミングする原則に従っており、システムをより柔軟で拡張しやすくします。
チャレンジ
簡単Factoryパターンを使って図形描画システムを構築しましょう!コード全体で図形オブジェクトを直接作成する代わりに、単純な文字列識別子に基づいてさまざまな種類の図形を生成するファクトリに、作成ロジックを集約します。
コードを4つのファイルに分けて整理します。
Shape.java:すべての図形に共通する契約として機能する、Shapeという名前のインターフェースをDefineします。インターフェースでは、戻り値を返さず、描画される図形の情報を出力する単一のメソッドdraw()をdeclareしてください。Shapes.java:Shapeインターフェースをimplementする3つのclassをCreateします。Circle-draw()メソッドでDrawing a Circleを出力します。Rectangle-draw()メソッドでDrawing a Rectangleを出力します。Triangle-draw()メソッドでDrawing a Triangleを出力します。ShapeFactory.java:図形の作成を処理するFactory classをCreateします。ShapeFactoryには、ShapeをreturnするstaticメソッドcreateShape(String type)を用意します。typeパラメータに基づいて、次のように処理します。- typeが
"circle"とequalsする場合、新しいCircleをreturnします - typeが
"rectangle"とequalsする場合、新しいRectangleをreturnします - typeが
"triangle"とequalsする場合、新しいTriangleをreturnします - その他の値の場合は、
nullをreturnします
- typeが
Main.java:Factoryシステムを組み合わせます!2つの入力、つまり2つの図形の種類(どちらもString)を受け取ります。各入力について、
ShapeFactoryを使って図形をCreateし、それをShape変数に格納します。Factoryが有効な図形(nullではない)をreturnした場合は、そのdraw()メソッドをcallします。nullをreturnした場合は、Unknown shape: [type]を出力します。[type]には、指定された入力が入ります。両方の入力を順番に処理し、それぞれを独自の出力行に表示します。
入力は順番に2つ与えられます。1つ目の図形の種類(String)と、2つ目の図形の種類(String)です。
Main classがnew Circle()やnew Rectangle()を直接使用していないことに注目してください。Shapeインターフェースについてだけknowし、オブジェクトの作成をFactoryに依頼しています。これがFactoryパターンの力です。clientコードがconcrete classから切り離されています!
自分で試してみよう
import java.util.Scanner;
class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
// 2つの図形タイプを読み取る
String type1 = scanner.nextLine();
String type2 = scanner.nextLine();
// TODO: ShapeFactoryを使用して最初の図形を作成する
// 図形がnullでない場合、draw()を呼び出す
// If the shape is null, print "Unknown shape: [type]"
// TODO: 2つ目の図形についても同様に行う
}
}
このレッスンには短いクイズがあります。レッスンを始めて解答し、進捗を記録しましょう。
オブジェクト指向プログラミングのすべてのレッスン
4継承
継承の基本 (extends)super キーワードメソッドのオーバーライド (@Override)コンストラクタチェーンObject クラス単一継承と多段階継承なぜ多重継承ができないのかまとめ:従業員の階層構造自分で練習してみよう: Javaオンラインコンパイラ