本文へスキップ
BecomeCoder

Javaデザインパターンコース · 第2章 生成に関するパターン ― オブジェクトの「作り方」を工夫する · レッスン4

Factory Method ― 「作る処理」を1か所にまとめる

ブラウザで完結

導入

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 という具体的なクラス名を一切書いていません。
  • MainShape インタフェースだけを知っていればよく、CircleSquare の存在を意識しません。
  • 新しい形状(例えば 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.createelse if (kind.equals("triangle")) { return new Triangle(); } を足します。

実際に動かしてみよう

下のエディタにJavaを書いて「実行」を押すと、学習用シミュレータが System.out.println の出力を表示します(本物のJVMではなく、教材の範囲を再現した軽量エンジンです)。クラス・継承・コレクションなども動きます。Scanner で入力を読む例は「標準入力」欄に値を入れてください。本文の例を書き換えて動かしてみましょう(Stream・ラムダ・スレッド・ファイル入出力など一部の機能は対象外です)。

Java — ブラウザ内で実行(学習用シミュレータ)

Javaの教材サブセットを動かす学習用シミュレータを読み込みます(本物のJVMではなく、動きを再現した軽量な自作エンジンです)。
スクロールして表示された時点でも自動で読み込まれます。