CodeGym/Java Blog/ランダム/デザインパターン: 抽象ファクトリー
John Squirrels
レベル 41
San Francisco

デザインパターン: 抽象ファクトリー

ランダム グループに公開済み
人のメンバー
やあ!今日は引き続きデザイン パターンの学習を進め、抽象的なファクトリーパターンについて説明します。 デザインパターン: アブストラクトファクトリー - 1レッスンで取り上げる内容は次のとおりです。
  • 抽象ファクトリーとは何か、そしてこのパターンがどのような問題を解決するかについて説明します。
  • ユーザー インターフェイスを通じてコーヒーを注文するためのクロスプラットフォーム アプリケーションのスケルトンを作成します。
  • 図やコードを確認するなど、このパターンの使用方法について学習します。
  • おまけとして、このレッスンには、Java を使用してオペレーティング システムの名前を決定し、その結果に応じて別のアクションを実行する方法を学ぶのに役立つ隠れたイースター エッグが含まれています。
このパターンを完全に理解するには、次のトピックに精通している必要があります。
  • Javaの継承
  • Java の抽象クラスとメソッド

抽象ファクトリーはどのような問題を解決しますか?

すべてのファクトリ パターンと同様に、抽象ファクトリは、新しいオブジェクトが正しく作成されることを保証するのに役立ちます。私たちはこれを使用して、相互接続されたオブジェクトのさまざまなファミリーの「生産」を管理します。相互接続されたオブジェクトのさまざまなファミリー...これは何を意味しますか? 心配しないでください。実際には、すべてが思っているよりも簡単です。まず、相互接続されたオブジェクトのファミリーとはどのようなものでしょうか? いくつかのタイプの部隊が関与する軍事戦略を開発していると仮定します。
  • 歩兵
  • 騎兵
  • 射手
これらのタイプのユニットは同じ軍隊で勤務するため、相互に接続されています。上記のカテゴリは、相互に接続されたオブジェクトのファミリーであると言えます。私たちはこれを理解しています。ただし、抽象ファクトリー パターンは、相互接続されたオブジェクトのさまざまなファミリーの作成を調整するために使用されます。ここでも複雑なことは何もありません。軍事戦略の例を続けましょう。一般に、軍事部隊は複数の異なる交戦当事者に属します。どちらの側に属するかに応じて、軍事ユニットの外観は大きく異なります。ローマ軍の歩兵、騎手、射手はバイキングの歩兵、騎手、射手とは異なります。軍事戦略では、さまざまな軍隊の兵士は、相互に接続されたオブジェクトのさまざまなファミリーです。プログラマーだったら面白いだろうね」彼の間違いにより、ナポレオン時代のフランスの軍服を着た兵士が、マスケット銃を構えてローマの歩兵隊の間を歩いているのが発見された。抽象的な工場設計パターンは、まさにこの問題を解決するために必要です。いいえ、タイムトラベルによって生じる可能性のある当惑の問題ではなく、相互に接続されたオブジェクトのさまざまなグループを作成することの問題です。抽象ファクトリーは、利用可能なすべての製品 (オブジェクトのファミリー) を作成するためのインターフェースを提供します。通常、抽象ファクトリには複数の実装があります。彼らはそれぞれ、いずれかのファミリーの製品を作成する責任を負います。私たちの軍事戦略には、抽象的な歩兵、射手、騎兵を作成する抽象的なファクトリーと、このファクトリーの実装が含まれます。例えば、ローマの軍団兵を作る工場とカルタゴの兵士を作る工場です。抽象化は、このパターンの最も重要な指針です。工場のクライアントは、抽象インターフェイスを通じてのみ工場とその製品を操作します。その結果、現在どの兵士が作成されているかを考える必要はありません。代わりに、この責任を抽象ファクトリーの具体的な実装に渡します。

コーヒーショップの自動化を続けましょう

最後のレッスン、ファクトリーメソッドパターンを研究しました。私たちはそれを利用してコーヒー事業を拡大し、いくつかの新しい店舗をオープンしました。今日も私たちはビジネスの近代化を続けます。抽象的なファクトリー パターンを使用して、オンラインでコーヒーを注文するための新しいデスクトップ アプリケーションの基礎を築きます。デスクトップ アプリケーションを作成するときは、クロスプラットフォームのサポートについて常に考慮する必要があります。私たちのアプリケーションは macOS と Windows の両方で動作する必要があります (ネタバレ: Linux のサポートは宿題として実装する必要があります)。私たちのアプリケーションはどのようなものになるでしょうか? 非常にシンプルです。テキスト フィールド、選択フィールド、ボタンで構成されるフォームになります。さまざまなオペレーティング システムを使用した経験がある場合は、Windows のボタンのレンダリングが Mac とは異なることに気づいたことがあるでしょう。他のことも同様に...さて、始めましょう。
  • ボタン
  • テキストフィールド
  • 選択フィールド
onClick免責事項: 各インターフェイスでは、onValueChanged、 、 などのメソッドを定義できますonInputChanged。言い換えれば、さまざまなイベント (ボタンを押す、テキストを入力する、選択ボックスで値を選択する) を処理できるメソッドを定義できます。例に負荷がかかりすぎないよう、またファクトリ パターンを検討する際にわかりやすくするために、ここではこれらすべてを意図的に省略しています。製品の抽象インターフェイスを定義しましょう。
public interface Button {}
public interface Select {}
public interface TextField {}
オペレーティング システムごとに、オペレーティング システムのスタイルでインターフェイス要素を作成する必要があります。Windows と MacOS 用のコードを作成します。Windows 用の実装を作成しましょう。
public class WindowsButton implements Button {
}

public class WindowsSelect implements Select {
}

public class WindowsTextField implements TextField {
}
次に、MacOS に対しても同じことを行います。
public class MacButton implements Button {
}

public class MacSelect implements Select {
}

public class MacTextField implements TextField {
}
素晴らしい。ここで、利用可能なすべての抽象製品タイプを作成する抽象ファクトリーに進むことができます。
public interface GUIFactory {

    Button createButton();
    TextField createTextField();
    Select createSelect();

}
素晴らしいです。ご覧のとおり、まだ複雑なことは何も行っていません。以下の内容もすべて簡単です。製品に例えて、OS ごとにさまざまなファクトリ実装を作成します。Windows から始めましょう:
public class WindowsGUIFactory implements GUIFactory {
    public WindowsGUIFactory() {
        System.out.println("Creating GUIFactory for Windows OS");
    }

    public Button createButton() {
        System.out.println("Creating Button for Windows OS");
        return new WindowsButton();
    }

    public TextField createTextField() {
        System.out.println("Creating TextField for Windows OS");
        return new WindowsTextField();
    }

    public Select createSelect() {
        System.out.println("Creating Select for Windows OS");
        return new WindowsSelect();
    }
}
何が起こっているかをさらに説明するために、メソッドとコンストラクター内にコンソール出力を追加しました。次に macOS の場合:
public class MacGUIFactory implements GUIFactory {
    public MacGUIFactory() {
        System.out.println("Creating GUIFactory for macOS");
    }

    @Override
    public Button createButton() {
        System.out.println("Creating Button for macOS");
        return new MacButton();
    }

    @Override
    public TextField createTextField() {
        System.out.println("Creating TextField for macOS");
        return new MacTextField();
    }

    @Override
    public Select createSelect() {
        System.out.println("Creating Select for macOS");
        return new MacSelect();
    }
}
各メソッド シグネチャは、メソッドが抽象型を返すことを示していることに注意してください。ただし、メソッドの内部では、製品の特定の実装を作成しています。これは、特定のインスタンスの作成を制御する唯一の場所です。次に、フォームのクラスを作成します。これは、フィールドがインターフェイス要素である Java クラスです。
public class CoffeeOrderForm {
    private final TextField customerNameTextField;
    private final Select coffeeTypeSelect;
    private final Button orderButton;

    public CoffeeOrderForm(GUIFactory factory) {
        System.out.println("Creating coffee order form");
        customerNameTextField = factory.createTextField();
        coffeeTypeSelect = factory.createSelect();
        orderButton = factory.createButton();
    }
}
インターフェイス要素を作成する抽象ファクトリは、フォームのコンストラクターに渡されます。特定の OS 用のインターフェイス要素を作成するために、必要なファクトリ実装をコンストラクターに渡します。
public class Application {
    private CoffeeOrderForm coffeeOrderForm;

    public void drawCoffeeOrderForm() {
        // Determine the name of the operating system through System.getProperty()
        String osName = System.getProperty("os.name").toLowerCase();
        GUIFactory guiFactory;

        if (osName.startsWith("win")) { // For Windows
            guiFactory = new WindowsGUIFactory();
        } else if (osName.startsWith("mac")) { // For Mac
            guiFactory = new MacGUIFactory();
        } else {
            System.out.println("Unknown OS. Unable to draw form :(");
            return;
        }
        coffeeOrderForm = new CoffeeOrderForm(guiFactory);
    }

    public static void main(String[] args) {
        Application application = new Application();
        application.drawCoffeeOrderForm();
    }
}
Windows でアプリケーションを実行すると、次の出力が得られます。
Creating GUIFactory for Windows OS
Creating coffee order form
Creating TextField for Windows OS
Creating Select for Windows OS
Creating Button for Windows OS
Mac では、出力は次のようになります。
Creating GUIFactory for macOS
Creating coffee order form
Creating TextField for macOS
Creating Select for macOS
Creating Button for macOS
Linux の場合:
Unknown OS. Unable to draw form :(
そして今、要約します。私たちは、インターフェイス要素が関連する OS 用に特別に作成された GUI ベースのアプリケーションのスケルトンを作成しました。作成したものを簡潔に繰り返します。
  • 入力フィールド、選択フィールド、ボタンで構成される製品ファミリー。
  • Windows と macOS の製品ファミリーのさまざまな実装。
  • 製品を作成するためのインターフェイスを定義する抽象ファクトリー。
  • 当社の工場には 2 つの実装があり、それぞれが特定の製品ファミリーの作成を担当します。
  • フィールドが抽象ファクトリを使用してコンストラクター内の必要な値で初期化される抽象インターフェイス要素であるフォーム (Java クラス)。
  • Application クラス このクラス内でフォームを作成し、目的のファクトリ実装をそのコンストラクターに渡します。
結論としては、抽象ファクトリー パターンを実装したということです。

抽象ファクトリー: 使い方

抽象ファクトリーは、具体的な製品クラスに縛られることなく、さまざまな製品ファミリーの作成を管理するための設計パターンです。このパターンを使用する場合は、次のことを行う必要があります。
  1. 製品ファミリーを定義します。それらが 2 つあると仮定します。
    • SpecificProductA1SpecificProductB1
    • SpecificProductA2SpecificProductB2
  2. ファミリ内の製品ごとに、抽象クラス (インターフェイス) を定義します。私たちの場合は次のようになります。
    • ProductA
    • ProductB
  3. 各製品ファミリー内で、各製品はステップ 2 で定義したインターフェイスを実装する必要があります。
  4. ステップ 2 で定義した各製品を作成するメソッドを使用して、抽象ファクトリーを作成します。この場合、これらのメソッドは次のようになります。
    • ProductA createProductA();
    • ProductB createProductB();
  5. 抽象ファクトリー実装を作成して、各実装が単一ファミリーの製品の作成を制御できるようにします。これを行うには、抽象ファクトリの各実装内で、特定の製品実装を作成して返すように、すべての作成メソッドを実装する必要があります。
次の UML 図は、上で概説した手順を示しています。 デザインパターン: アブストラクトファクトリー - 3次に、これらの手順に従ってコードを記述します。
// Define common product interfaces
public interface ProductA {}
public interface ProductB {}

// Create various implementations (families) of our products
public class SpecificProductA1 implements ProductA {}
public class SpecificProductB1 implements ProductB {}

public class SpecificProductA2 implements ProductA {}
public class SpecificProductB2 implements ProductB {}

// Create an abstract factory
public interface AbstractFactory {
    ProductA createProductA();
    ProductB createProductB();
}

// Implement the abstract factory in order to create products in family 1
public class SpecificFactory1 implements AbstractFactory {

    @Override
    public ProductA createProductA() {
        return new SpecificProductA1();
    }

    @Override
    public ProductB createProductB() {
        return new SpecificProductB1();
    }
}

// Implement the abstract factory in order to create products in family 2
public class SpecificFactory2 implements AbstractFactory {

    @Override
    public ProductA createProductA() {
        return new SpecificProductA2();
    }

    @Override
    public ProductB createProductB() {
        return new SpecificProductB2();
    }
}

宿題

材料を強化するには、次の 2 つのことを行うことができます。
  1. コーヒー注文アプリケーションを Linux でも動作するように改良します。
  2. あらゆる軍事戦略に関与するユニットを生産するための独自の抽象ファクトリーを作成します。これは、現実の軍隊を使った歴史的な軍事戦略でも、オーク、ノーム、エルフを使ったファンタジーの戦略でも構いません。大切なのは、自分の興味のあるものを選ぶことです。創造力を発揮して、コンソールにメッセージを出力し、パターンについて楽しく学習してください。
コメント
  • 人気
  • 新規
  • 古い
コメントを残すには、サインインしている必要があります
このページにはまだコメントがありません