「ヘッドファーストデザインパターン」の研究ノート - 工場パターン

今日はとにかく、それは書き込みを継続することで、私が忘れてしまった最初の数日間です。数日前にも、我々は改善する必要があり、今日完全に努めています!

のトーンの例

ピザ店の所有者として、私たちは多くのピザの種類、焼成して、販売するためにパッケージ化されたピザの種類、何を顧客のニーズを決定するためにコードを追加する必要性を設計する必要があるので、ピザの種類を販売する必要があります。

私たちのピザが静的ではない、新しいタイプを提供する必要があるが、いくつかの悪いピザは、我々は、コードを変更する必要があり、この時間は棚を売却することが必要であるされています。

私たちは別のカテゴリに、一部のオブジェクトを作成する必要があるので、ピザは、別のオブジェクト、ピザオブジェクトを作成するために特別に作成されたオブジェクトを取得するコードを作成することです。この新しいオブジェクトは、私たちが呼んで「工場。」

私たちはピザだけ加工工場を呼び出す必要があるときにオブジェクトを作成し、ベーキング、スライス、ボクシングの動作をしますので、今、私たちは、簡単な工場を持っていること。今、私たちは、このようなシンプルなピザの工場をしなければなりません。

シンプル工場コード

まずピザスーパークラスが属性を定義し、そのタイプを記述し、いくつかの処理方法があります。

public class Pizza {
    String description = "pizza";

    public void prepare() {
        System.out.println("prepare: " + description);
    }
    public void bake() {
        System.out.println("bake: " + description);
    }
    public void cut() {
        System.out.println("cut: " + description);
    }
    public void box() {
        System.out.println("box: " + description);
        System.out.println(description + " successful");
    }
}

ピザは、次の修正に親クラスの継承プロパティといういくつかのサブクラスを定義します。

public class CheesePizza extends Pizza {
    public CheesePizza() {
    	this.description = "cheese pizza";
    }
}

public class ClamPizza extends Pizza {
    public ClamPizza() {
        this.description = "clam pizza";
    }
}

public class PepperoniPizza extends Pizza {
    public PepperoniPizza() {
        this.description = "pepperoni pizza";
    }
}

public class VeggiePizza extends Pizza {
    public VeggiePizza() {
        this.description = "veggie pizza";
    }
}

簡単ピザ工場コード、createPizza(文字列型)法、必要な戻りピザオブジェクトを渡すことにより、ピザの種類。

public class SimplePizzaFactory {
    public Pizza createPizza(String type) {
        Pizza pizza = null;

        if (type.equals("cheese")) {
            pizza = new CheesePizza();
        } else if (type.equals("pepperoni")) {
            pizza = new PepperoniPizza();
        } else if (type.equals("clam")) {
            pizza = new ClamPizza();
        } else if (type.equals("veggie")) {
            pizza = new VeggiePizza();
        }
        return pizza;
    }
}

ピザを作るために必要に応じてタイプを渡すピザファクトリー・プロパティー、ピザを作る方法、などのピッツェリアコード、。

public class PizzaStore {
    SimplePizzaFactory factory;
    public PizzaStore(SimplePizzaFactory factory) {
        this.factory = factory;
    }

    public Pizza orderPizza(String type) {
        Pizza pizza = factory.createPizza(type);

        pizza.prepare();
        pizza.bake();
        pizza.cut();
        pizza.box();
        return pizza;
    }
}

試験方法の定義。

	public static void main(String[] args) {
        new PizzaStore(new SimplePizzaFactory()).orderPizza("cheese");
    }

ピザが作成され、実際には、ああ、単に工場のデザインパターンではないプログラミングの習慣に、より似ています、。頻繁に使用しているため、と考えるのが通例である「シンプルなファクトリパターン。」

シンプルで直接作業、工場OEMのオブジェクトを作成し、当社のピザのピザ店を排除する工場が、唯一の「使用」は良いピザを作成し、簡単な工場出荷時のパターンは、このアプローチによって責任の分割を達成するためには、特別な植物を提供しますオブジェクトは、特定のクラス名を知らなくても製品を使用する際に必要なオブジェクトを作成し、のみ提供する必要があり、特定の識別ユーザーはメモリの不必要な量を排除し、作成するクラスの名前を覚えておく必要はありませんので、対応するオブジェクトを作成するために。

しかし、私たちの工場を対象に起因するのオブジェクトを作成するためのすべてのロジックを集中小さなバグ、このファクトリオブジェクトのストライキを、仮定、そして私たちのシステム全体が影響を受け、問題のこの部分のためになること。「 -クローズ原理オープン」の新製品を追加するために、工場はより多くの追加のロジック、あまりにも複雑になる。このファクトリクラス、およびシステムの拡張やメンテナンスを助長されていませんを変更する必要がありました弱体化があります。

ファクトリメソッドパターン

すべてのモデルは、パッケージオブジェクトを作成するために使用する工場です。Factory Methodパターンは、サブクラスは、オブジェクトが作成されたものを決定させることである、プロセスの目的は、パッケージを作成したオブジェクトを打つことです。

あなたが悪いのサブクラスを作成するための抽象ファクトリメソッドを定義する抽象クラスのトップクリエイターはクリエイターがしばしば抽象的製品に依存しているコード、およびこれらの抽象の製品が含まれている、ある製造サブクラスでCreatorはどこ特定の製品を製造するために知っておく必要はありません。

今、私たちはPizzaStoreコードを見て。

public abstract class PizzaStore {
    abstract Pizza createPizza(String item);

    public Pizza orderPizza(String type) {
        Pizza pizza = createPizza(type);
        System.out.println("--- Making a " + pizza.description + "---");
        pizza.prepare();
        pizza.bake();
        pizza.cut();
        pizza.box();
        return pizza;
    }
}

サブクラスのオブジェクトを作成するための抽象メソッドcreatePizza(文字列の項目)、およびorderPizza(文字列型)は、私たちが呼び出すコードオブジェクトが完成ピザをパッケージ返さ作成したクラスの作成者です。

その後、我々は、クラスの作成者を見てください。

public class ChicagoPizzaStore extends PizzaStore {
    @Override
    Pizza createPizza(String item) {
        if (item.equals("cheese")) {
            return new ChicagoStyleCheesePizza();
        } else if (item.equals("veggie")) {
            return new ChicagoStyleVeggiePizza();
        } else if (item.equals("clam")) {
            return new ChicagoStyleClamPizza();
        } else if (item.equals("pepperoni")) {
            return new ChicagoStylePepperoniPizza();
        }
        return null;
    }
}

public class NYPizzaStore extends PizzaStore {
    @Override
    Pizza createPizza(String item) {
        if (item.equals("cheese")) {
            return new NYStyleCheesePizza();
        } else if (item.equals("clam")) {
            return new NYStyleClamPizza();
        } else if (item.equals("pepperoni")) {
            return new NYStylePepperoniPizza();
        } else if (item.equals("veggie")) {
            return new NYStyleVeggiePizza();
        }
        return null;
    }
}

PizzaStoreクラスの継承の上、createPizza(文字列の項目)メソッドを達成するためにピザのさまざまなニーズに応じて異なるオブジェクトを作成し、親のために作成されたオブジェクトのサブクラスでは、完成したパッケージのピザの製造が完了しているを使用しています。これは、我々はちょうどあなたがサブクラスを作成する必要があるオブジェクトを作成するために、パッケージの目的は、オブジェクトを作成するために言ったことです。

私たちのスーパークラスを続けると、ピザは、製品を見てみたいです。

public abstract class Pizza {
    String description = "Pizza";

    void prepare() {
        System.out.println("Prepare " + description);
    }

    void bake() {
        System.out.println("Bake " + description);
    }

    void cut() {
        System.out.println("Cut " + description);
    }

    void box() {
        System.out.println("Box " + description);
        System.out.println(description + " successful");
    }
}

何も特別なは、種類のピザの、いくつかの準備ができて、ベーキング、スライスや梱包方法が何であるかを説明する説明属性があり、作成者スーパークラスでorderPizza(文字列型)が使用されています。次のコードは、名前だけへの2枚のピザであるなど、他ではちょうどdescription属性を変更するには、常に同じです。

public class ChicagoStyleCheesePizza extends Pizza {
    public ChicagoStyleCheesePizza() {
        this.description = "Chicago style cheese pizza";
    }
}

public class NYStyleClamPizza extends Pizza {
    public NYStyleClamPizza() {
        description = "NY style clam pizza";
    }
}

最後に、我々はテストクラスを見てください。

public class Test {
    public static void main(String[] args) {
        ChicagoPizzaStore chicagoPizzaStore = new ChicagoPizzaStore();
        NYPizzaStore nyPizzaStore = new NYPizzaStore();

        chicagoPizzaStore.orderPizza("cheese");
        System.out.println("-------------------");

        chicagoPizzaStore.orderPizza("clam");
        System.out.println("-------------------");

        chicagoPizzaStore.orderPizza("pepperoni");
        System.out.println("-------------------");

        chicagoPizzaStore.orderPizza("veggie");
        System.out.println("-------------------");

        nyPizzaStore.orderPizza("cheese");
        System.out.println("-------------------");

        nyPizzaStore.orderPizza("clam");
        System.out.println("-------------------");

        nyPizzaStore.orderPizza("pepperoni");
        System.out.println("-------------------");

        nyPizzaStore.orderPizza("veggie");
    }
}

ただ、もちろん、私は、必要に応じて、ピザを参照するための変数を宣言していないピザを詰め得ることができます必要に渡された文字列を渡し、orderPizza(文字列型)メソッドを呼び出して、2つのピザ屋オブジェクトを作成し、あなたは変数を宣言することができますPizza pizza = nyPizzaStore.orderPizza("veggie")

製品のスーパークラスと彼らは彼らの創造者、スーパークラスとサブクラスのサブクラスパラレルクラス階層、彼らは抽象クラスである、抽象クラスは、多くの特定のサブクラスを持って、各サブクラスは独自の具体的な実装を持っています。

ファクトリメソッドパターンを定義する:Factory Methodパターンは、オブジェクトを作成するためのインタフェースを定義するが、サブクラスは、1つのクラスをインスタンス化します。サブクラスに延期インスタンスを生成するクラスファクトリメソッドをしてみましょう。

工場モデルの方法は、パッケージの特定の型のインスタンスを作成することができます。抽象スーパークリエータでは、そこにオブジェクトファクトリメソッドを作成するために使用することができる達成するための他の方法がありますが、この位置を達成するための製品を作成するためには、抽象ファクトリメソッドのサブクラスです。

サブクラスが作成される特定の製品を知っていないオブジェクトの作成が実際にクラスの作成者を指している製品を決めましょう。種類に応じて、製品であるオブジェクトの実際の作成を決定するためにどのクラスを選択する場合のみです。

オブジェクトコードを作成するときにファクトリメソッドパターンが繰り返しの多くを必要とし、クライアントは、製品を作成する必要があるかの事情を知っている必要はありません。ユーザーとして、私達はちょうど私たちが使用するオブジェクトと快適を作成できるように、どの植物を知っている必要があり、同様に何を特定する必要があります。Factory Methodパターンは非常に明確である、我々はコードから見ることができる欠点、あなたが舞い上がる簡単にクラスを作成する必要があり、多くの、システムの複雑さを増す、それはプログラマを理解することの難しさを増大させることができます。

このデザインパターンでも、設計原理を必要とする- 依存関係逆転の原則:抽象的に依存すると、特定のクラスに依存しません。

レベルに関係なくまたは基礎部品の抽象に依存すべき、高レベルのコンポーネントは、低レベルのコンポーネントに依存せ、およびすることはできません。

この例では、PizzaStoreは、「高レベルのコンポーネントを」で、ピザは私たちの原則に沿って、「低レベルのコンポーネント」、PizzaStore依存ピザ抽象クラスです。

Abstract Factoryパターン

今起因する非常に成功への私たちのピザは、フランチャイズに参加することがあり、そして私たちのピザの成功は、理由は私たちの原材料の高品質で新鮮で、私たちは新しい増加したので、今、私たちは、私たちの原料の流れに合わせても、ピザのフランチャイズを作りたいです原料工場、原材料の品質を確保します。

原料工場の界面で見てみましょう。

public interface PizzaIngredientFactory {

    public Dough createDough();
    public Sauce createSauce();
    public Cheese createCheese();
    public Veggies[] createVeggies();
    public Pepperoni createPepperoni();
    public Clams createClam();

}

各地域の工場のクラスは、このクラスのサブクラスであること、および原材料を作成するための各メソッドを実装する必要がありますので、工場インターフェースは、すべての原材料を作成する責任があります。

私たちは、その後、上記のインターフェースを実現するために、原材料のニューヨークファクトリを作成しました。

public class NYPizzaIngredientFactory implements PizzaIngredientFactory {
    @Override
    public Dough createDough() {
        return new ThinCrustDough();
    }

    @Override
    public Sauce createSauce() {
        return new MarinaraSauce();
    }

    @Override
    public Cheese createCheese() {
        return new ReggianoCheese();
    }

    @Override
    public Veggies[] createVeggies() {
        Veggies veggies[] = {new Garlic(), new Onion(), new Mushroom(), new RedPepper()};
        return veggies;
    }

    @Override
    public Pepperoni createPepperoni() {
        return new SlicedPepperoni();
    }

    @Override
    public Clams createClam() {
        return new FreshClams();
    }
}

今ピザのスーパークラスを作成します。

public abstract class Pizza {
    String name;
    Dough dough;
    Sauce sauce;
    Veggies[] veggies;
    Cheese cheese;
    Pepperoni pepperoni;
    Clams clams;

    abstract void prepare();

    void bake() {
        System.out.println("Bake for 25 minutes at 350");
    }

    void cut() {
        System.out.println("Cutting the pizza into diagonal slices");
    }

    void box() {
        System.out.println("Place pizza in official PizzaStore box");
    }

    void setName(String name) {
        this.name = name;
    }

    String getName() {
        return name;
    }

    @Override
    public String toString() {
        return "Pizza{" +
                "name='" + name + '\'' +
                ", dough=" + dough +
                ", sauce=" + sauce +
                ", veggies=" + Arrays.toString(veggies) +
                ", cheese=" + cheese +
                ", pepperoni=" + pepperoni +
                ", clams=" + clams +
                '}';
    }
}

ピザ、プロパティがいくつか含まれている、それが私たちの生の材料特性で、その後、抽象メソッドは、(準備がある)は、私たちの原料を収集、ピザを作るために必要なステップがあります。

ピザのいくつかの品種の次の生産。

public class CheesePizza extends Pizza {
    PizzaIngredientFactory ingredientFactory;

    public CheesePizza(PizzaIngredientFactory ingredientFactory) {
        this.ingredientFactory = ingredientFactory;
    }

    @Override
    void prepare() {
        System.out.println("Preparing " + name);
        dough = ingredientFactory.createDough();
        sauce = ingredientFactory.createSauce();
        cheese = ingredientFactory.createCheese();
    }
}

public class ClamPizza extends Pizza {
    PizzaIngredientFactory ingredientFactory;

    public ClamPizza(PizzaIngredientFactory ingredientFactory) {
        this.ingredientFactory = ingredientFactory;
    }

    @Override
    void prepare() {
        System.out.println("Preparing " + name);
        dough = ingredientFactory.createDough();
        sauce = ingredientFactory.createSauce();
        cheese = ingredientFactory.createCheese();
    }
}

これは、属性、植物原料の特性、()メソッドを準備作成するために、工場での原料の使用が含まれています。これには、完全にピザクラス原料を、あなたは簡単に再利用、原材料へのアクセスは(彼のサブクラスの実装に用意されてできる方法をされて気にしない、魔法の場所、分離創造とピザスーパークラスの原料であります)共同設立方法や植物の性質。私たちはピザの種類が必要な場合は、ピザは、サブクラスの継承スーパークラスを作成し、対応する原料を得るために、対応するピザピザファクトリーを渡す必要があります。

今、私たちはピザ店に戻って行きます。

public abstract class PizzaStore {
    abstract Pizza createPizza(String item);

    public Pizza orderPizza(String type) {
        Pizza pizza = createPizza(type);
        System.out.println("--- Making a " + pizza.name + "---");
        pizza.prepare();
        pizza.bake();
        pizza.cut();
        pizza.box();
        return pizza;
    }
}

public abstract class PizzaStore {
    abstract Pizza createPizza(String item);

    public Pizza orderPizza(String type) {
        Pizza pizza = createPizza(type);
        System.out.println("--- Making a " + pizza.name + "---");
        pizza.prepare();
        pizza.bake();
        pizza.cut();
        pizza.box();
        return pizza;
    }
}

public class NYPizzaStore extends PizzaStore {
    @Override
    Pizza createPizza(String item) {
        Pizza pizza = null;
        PizzaIngredientFactory ingredientFactory = new NYPizzaIngredientFactory();
        if (item.equals("cheese")) {
            pizza = new CheesePizza(ingredientFactory);
            pizza.setName("New York Style Cheese Pizza");
        } else if (item.equals("veggie")) {
            pizza = new VeggiePizza(ingredientFactory);
            pizza.setName("New York Style Veggie Pizza");
        } else if (item.equals("clam")) {
            pizza = new ClamPizza(ingredientFactory);
            pizza.setName("New York Style Clam Pizza");
        } else if (item.equals("pepperoni")) {
            pizza = new PepperoniPizza(ingredientFactory);
            pizza.setName("New York Style Pepperoni Pizza");
        }
        return pizza;
    }
}

対応する対応する識別子によって作成されたニューヨークのピザのピザが、あなたはピザのオブジェクトを作成するときに、ピザピザ工場は原料を提供することを目的に合格しました。

Abstract Factoryパターンを要約すると、我々は植物の新しいタイプを導入し、抽象的な工場が提供するインタフェースを介して、ピザの家族を作成するための原料は、あなたが、書き込みのコードにこのインタフェースを使用する製品ファミリを作成することができ、私たちのコードをするために、実際の植物から分離されます様々な製品を製造するために、異なるコンテキストでの植物の多様性を実現しています。

そのため、我々は作成方法の原料は、サブクラスファクトリに実装されているので、私たちは新しいファクトリクラスを作成することにより、原料の交換を達成することができます。

Abstract Factoryパターンは、明示的に特定のクラスを指定する必要がなく、関連または依存オブジェクトの家族を作成するためのインタフェースを提供します。

抽象ファクトリーは、顧客が実際の出力イエスのどのような特定の製品を知らなくても、関連製品抽象インタフェースのグループを作成することができます。Abstract Factoryパターンは、内部クラスの制約で製品ファミリの最大の特徴ですが、欠点は、これらの製品ファミリを拡張する事は非常に面倒ですが、必要性、新製品、ファクトリクラスのすべてのほとんどすべての変更なので、製品の場合慎重に分割構造。

ここでは、モデルはいくつかの工場の上に導入され、その目的は、使用中、分離することで、限り、我々は結合度を軽減することを目指して、特定のパターンが何であるかを区別する必要が到達することはできません。

公開された26元の記事 ウォンの賞賛2 ビュー2329

おすすめ

転載: blog.csdn.net/qq_42909545/article/details/104836222