導入
if の分岐であちこちに new Circle() や new Square() が散らばっていると、新しい種類を追加するたびにコードの複数箇所を修正することになります。Factory Method(ファクトリメソッド) は、「どのクラスを作るか」の判断を1つの専用メソッドに閉じ込めるパターンです。
説明
呼び出し側は「作ってもらう」だけで、具体的にどのクラスが生成されるかを知る必要がありません。
public class Main {
public static void main(String[] args) {
Shape s1 = ShapeFactory.create("circle");
Shape s2 = ShapeFactory.create("square");
s1.draw();
s2.draw();
}
}
interface Shape {
void draw();
}
class Circle implements Shape {
public void draw() {
System.out.println("○ を描きました");
}
}
class Square implements Shape {
public void draw() {
System.out.println("□ を描きました");
}
}
class ShapeFactory {
static Shape create(String kind) {
if (kind.equals("circle")) {
return new Circle();
} else if (kind.equals("square")) {
return new Square();
}
throw new IllegalArgumentException("不明な形状: " + kind);
}
}
classDiagram
Shape <|.. Circle
Shape <|.. Square
ShapeFactory ..> Shape : creates
class Shape {
<<interface>>
+draw()
}
class ShapeFactory {
+create(kind) Shape$
}
ShapeFactory.create("circle")… 呼び出し側は"circle"という文字列だけを渡し、Circleという具体的なクラス名を一切書いていません。MainはShapeインタフェースだけを知っていればよく、CircleやSquareの存在を意識しません。- 新しい形状(例えば
Triangle)を追加したいときも、修正するのはShapeFactoryの中だけです。呼び出し側のコードは変更不要——これは第1章で学んだ 開放閉鎖の原則(OCP) そのものです。
やってみよう
下のエディタを実行し、"circle" と "square" それぞれで正しい形が描かれることを確認しましょう。ShapeFactory.create("hexagon") のように存在しない種類を渡すとどうなるか(IllegalArgumentException)も試してみてください。
演習
Triangle クラスを作って Shape を実装し、draw() で △ を描きました と表示させてください。ShapeFactory.create に "triangle" の分岐を追加し、main から ShapeFactory.create("triangle") を呼んで draw() してください。
ヒント1を見る
class Triangle implements Shape { public void draw() { System.out.println("△ を描きました"); } }。
ヒント2を見る
ShapeFactory.create に else if (kind.equals("triangle")) { return new Triangle(); } を足します。