「労働者が自分の仕事をうまくやりたいなら、まず自分の道具を研ぎ澄まさなければなりません。」 - 孔子、「論語。陸霊公」
表紙 > プログラミング > シンプルファクトリー

シンプルファクトリー

2024 年 11 月 17 日に公開
ブラウズ:706

シンプルファクトリーとは何ですか?

シンプルファクトリーはデザインパターンではありません。オブジェクトの作成をクライアント コードから切り離すだけです。言い換えれば、シンプル ファクトリは、インスタンス化ロジックを別のクラスに移動することによって、オブジェクトのインスタンス化をカプセル化します。

シンプル ファクトリは、ファクトリ パターンと混同されることがよくあります。それらの違いを明確にするために、Simple Factory を研究していきます。また、Simple Factory を学習すると、Factory パターンを簡単に理解できるようになります。

シンプルファクトリーで解決できる問題とは?

具体的な実装へのプログラミングは、アプリケーションの保守が非常に困難になるため、避けるべきです。インターフェイスに合わせてプログラムすることが常に望ましいです。クライアント コードで具象クラスをインスタンス化する場合、Simple Factory はオブジェクトの作成をクライアントから分離できるため、Simple Factory が便利です。これにより、アプリケーションの拡張性と保守性が向上します。

問題

バーガーショップ向けのシステム開発を行っております。システムは、ビーフバーガー、チキンバーガーなどのさまざまなバーガーを作成する必要があります。

最初の試みは次のようになります:

// Client orders a burger
Burger orderBurger(String type) {
    Burger burger;

    if (type.equals("beef")) {
        burger = new BeefBurger();
    } else if (type.equals("chicken")) {
        burger = new ChickenBurger();
    } else if (type.equals("fish")) {
        burger = new FishBurger();
    }

    burger.prepareBun();
    burger.grillPatty();
    burger.addToppings();
    burger.wrap();

    return burger;
}

問題は、インターフェイスではなく実装に向かってコーディングしていることです。どこ? if ステートメントを使用し、ハンバーガーの種類に基づいて具象クラスをインスタンス化します。
なぜそれが問題なのでしょうか?私たちのクライアント コードはオブジェクト作成と密接に結合しているため、柔軟性が低下します。フィッシュバーガーをもう販売しないで、ベジバーガーの販売を開始するとします。クライアントコードにアクセスして変更する必要があります。つまり、変更が禁止されていません。

解決

この問題を解決するには、オブジェクトの作成のみを担当する別のクラスを作成します。そうすれば、クライアント コードはオブジェクトの作成について心配する必要がなくなり、抽象化に依存できるようになります。この技術は 「変化するものをカプセル化する」 として知られています。具体的なオブジェクトのインスタンス化に関するコードは頻繁に変更されると予想されますが、prepareBun()、grillPatty()、addToppings()、wrap() プロセスは将来的にすべてのハンバーガーで同じままになる可能性があります。
シンプル ファクトリの利点は、他のクラスで再利用できることです。 SimpleBurgerFactory.createBurger() メソッドを使用する BurgerRestaurant、BurgerCateringShop などの他のクライアント クラスがある可能性があります。

Simple Factory

  1. クライアント
    クライアントは SimpleBurgerFactory を通じて特定のバーガー オブジェクトをインスタンス化します。クライアントの観点から見ると、どの具体的なバーガーが作成されるかはわかりません。つまり、オブジェクト作成ロジックはクライアントから切り離されています。

  2. シンプルバーガーファクトリー
    このクラスは、さまざまなもの、この場合はオブジェクト作成ロジックをカプセル化します。 createBurger() は、クライアントがこのクラスを使用してオブジェクトをインスタンス化したいため、静的メソッドとして宣言されています (もちろん、インスタンス化する前にインスタンスを持つことはできません)。 createBurger() は BurgerType 列挙型を受け入れて、作成するハンバーガーの種類を決定します。

  3. バーガー
    この抽象クラスは、すべてのバーガー間で共通のインターフェイスを提供し、デフォルトの動作を定義します。

  4. バーガーのサブクラス
    弊社の具体的な製品をご紹介します。 Burger クラスを拡張する限り、メソッドをオーバーライドすることで特定の動作を実装できます。

構造

Simple Factory

コード

public enum BurgerType {
    BEEF,
    CHICKEN,
    FISH,
    VEGGIE
}
// Abstract Product
public abstract class Burger {

    public BurgerType burgerType;
    public List toppings = new ArrayList();

    public void prepareBun() {
        System.out.println("Preparing a bun");
    }

    public void grillPatty() {
        if (burgerType == null) {
            throw new IllegalStateException("pattyType is undefined");
        }
        System.out.println("Grill a "   burgerType   " patty");
    }

    public void addToppings() {
        for (String item : toppings) {
            System.out.println("Add "   item);
        }
    }

    public void wrap() {
        System.out.println("Wrap a burger up");
    }
}
// Concrete product
public class BeefBurger extends Burger {

    public BeefBurger() {
        burgerType = BurgerType.BEEF;
        List items = List.of("lettuce", "pickle slices", "tomato slice", "BBQ sauce");
        toppings.addAll(items);
    }
}
// Concrete product
public class VeggieBurger extends Burger {

    public VeggieBurger() {
        burgerType = BurgerType.VEGGIE;
        List items = List.of("smoked paprika", "garlic chips", "crushed walnuts", "veggie sauce");
        toppings.addAll(items);
    }

    // Concrete product can implement specific behavior that differs from other products
    @Override
    public void wrap() {
        System.out.println("Wrapping paper shouldn't print any meats but vegetables");
    }
}
// Simple factory, responsible for instantiating an object
public class SimpleBurgerFactory {

    public static Burger createBurger(BurgerType type) {
        return switch (type) {
            case BEEF -> new BeefBurger();
            case CHICKEN -> new ChickenBurger();
            case FISH -> new FishBurger();
            case VEGGIE -> new VeggieBurger();
            default -> throw new IllegalArgumentException("unknown burger type");
        };
    }
}
public class Client {

    public static void main(String[] args) {
        Burger burger = orderBurger(BurgerType.VEGGIE);
        System.out.println(burger); // Check if the object is actually veggie burger
    }

    public static Burger orderBurger(BurgerType type) {
        // Factory is responsible for object creation
        Burger burger = SimpleBurgerFactory.createBurger(type);

        burger.prepareBun();
        burger.grillPatty();
        burger.addToppings();
        burger.wrap();

        return burger;
    }
}

出力:

Preparing a bun
Grill a VEGGIE patty
Add smoked paprika
Add garlic chips
Add crushed walnuts
Add veggie sauce
Wrapping paper shouldn't print any meats but vegetables
com.factories.simpleFactory.VeggieBurger@9807454

落とし穴

  • オブジェクトのインスタンス化のための意思決定コードは、より複雑になる場合があります。そのような場合は、代わりに Factory メソッドを使用することを検討してください。

工場出荷時パターンとの比較

  • シンプル ファクトリでは、通常、作成する製品のタイプを決定するファクトリ クラスが 1 つありますが、ファクトリ パターンでは複数のファクトリが導入される場合があります。
  • シンプル ファクトリでは、静的メソッドを使用してオブジェクトを作成することが多く、呼び出しは簡単ですが、拡張は困難です。一方、Factory メソッドはスーパー クラスで抽象メソッドを使用します。これはすべてのファクトリとサブクラスのインターフェイスとして機能し、オブジェクトのインスタンス化のための具体的な実装を提供します。

すべてのデザイン パターンの実装をここで確認できます。
GitHub リポジトリ


追記
技術ブログを書くのは初めてです。文章を改善するためのアドバイスや、わかりにくい点がある場合は、コメントを残してください。
読んでいただきありがとうございます:)

リリースステートメント この記事は次の場所に転載されています: https://dev.to/sota_333ad4b72095606ab40c/simple-factory-3bnl?1 侵害がある場合は、[email protected] に連絡して削除してください。
最新のチュートリアル もっと>

免責事項: 提供されるすべてのリソースの一部はインターネットからのものです。お客様の著作権またはその他の権利および利益の侵害がある場合は、詳細な理由を説明し、著作権または権利および利益の証拠を提出して、電子メール [email protected] に送信してください。 できるだけ早く対応させていただきます。

Copyright© 2022 湘ICP备2022001581号-3