HeadFirst 设计模式 - Chapte 4工厂设计模式

1929 查看

工厂模式

定义

工厂方法模式定义了一个创建对象的接口,但由子类决定(“决定”是指在编写创建者类creator类时,不需要知道实际创建的product是哪一个。选择使用了哪个子类,自然就决定了实际创建的产品是什么)要实例化的类是哪一个。
工厂方法让类把实例化推迟到子类。ConcreteCreator负责创建一个或多个具体产品,只有ConcreteCreator类知道如何创建这些产品(组合使用了ConcreteProduct)。

简单工厂模式是让一个对象负责所有具体类的实例化,而工厂模式是让一群子类(NYStylePizzaStore, ChicagoStylePizzaStore)来负责实例化。工厂方法 createPizza()是抽象的,所以会依赖子类来处理对象的创建 --- 工厂模式通过让子类决定该创建的对象是什么,来达到将对象创建的过程封装的目的。


Creator:

PizzaStore实现:

javapublic abstract class PizzaStore {

    public final Pizza orderPizza(String type) // order system
    {
        Pizza pizza;
        pizza =  createPizza(type);  
        pizza.prepare();
        pizza.bake();
        pizza.cut();
        pizza.box();
        return pizza;
    }
    abstract Pizza createPizza(String type); // factory method
}
javapublic class ChicagoPizzaStore extends PizzaStore {
    Pizza pizza = null;
    @Override
    Pizza createPizza(String type) {
        if(type.equals("cheese")){
            pizza = new ChicagoStyleCheesePizza();  // create specific class 
        }else if(type.equals("pepperoni")){
            pizza = new NYStylePepperoniPizza(); // create specific class 
        }else if (type.equals("clam")){
            pizza = new NYStyleClamPizza(); // create specific class 
        }else if (type.equals("veggie")){
            pizza = new NYStyleVeggiePizza(); // create specific class 
        }
        return pizza;
    }
}
javapublic class NYPizzaStore extends PizzaStore {
    Pizza pizza = null;
    @Override
    Pizza createPizza(String type) {
        if(type.equals("cheese")){
            pizza = new NYStyleCheesePizza();  // create specific class 
        }else if(type.equals("pepperoni")){
            pizza = new NYStylePepperoniPizza(); // create specific class 
        }else if (type.equals("clam")){
            pizza = new NYStyleClamPizza(); // create specific class 
        }else if (type.equals("veggie")){
            pizza = new NYStyleVeggiePizza(); // create specific class 
        }
        return pizza;
    }
}

Products:

Pizza的实现

javaimport java.util.*;
public abstract class Pizza {
    String name;
    String dough;
    String sauce;
    ArrayList<String> toppings = new ArrayList<String>();

    public void prepare(){
        System.out.println("Preparing " + name);
        System.out.println("Tossing dough");
        System.out.println("Adding sauce ");
        System.out.println("Adding toppings");
        for (int i = 0;i<toppings.size();i++){
            System.out.println(" " + toppings.get(i));
        }
    }
    public void bake(){
        System.out.println("Bake for 25 mins at 350");
    }

    public void cut(){
        System.out.println("Cutting the pizza into diagonal slics");
    }
    public void box(){
        System.out.println("Place pizza in official PizzaStore box");
    }
    public String getName(){
        return name;
    }
}
javapublic class NYStyleCheesePizza extends Pizza{
    public NYStyleCheesePizza(){
        name = "NY Style Sauce and Cheese Pizza";
        dough = "Thin Crust Dough";
        sauce = "Marinara Sauce";
        toppings.add("Grated Regginao Cheese");
    }
}

测试类

javapublic class PizzaTestDrive {
    public static void main(String[] args){
        // create two stores
        PizzaStore nyStore = new NYPizzaStore(); 
        PizzaStore chicagoStore = new ChicagoPizzaStore();
        Pizza pizza = nyStore.orderPizza("cheese");
        System.out.println("Ethan ordered a" + pizza.getName() + "\n");
        pizza = chicagoStore.orderPizza("cheese");
        System.out.println("Joel ordered a" + pizza.getName() + "\n");
    }
}

抽象工厂模式

定义

抽象工厂模式提供一个接口,用于创建相关或依赖对象的家族(使用抽象的接口来创建一组相关的产品),而不需要明确指定具体类。

这个接口内的每个方法都负责创建一个具体的产品,同时我们利用实现抽象工厂的子类来提供这些具体的做法。

好处

创建产品家族 + 将相关产品集合起来。

具体实现
AbstractFactory接口创建一个产品家族

javapublic interface PizzaIngredientFactory {
    public Dough createDough();
    public Sause createSauce();
    public Cheese createCheese();
    public Veggies[] createVeggies();
    public Pepperoni createPepperoni();
    public Clams createClam();
}

具体工厂实现不同的产品家族。

javapublic class NYPizzaIngredientFactory implements PizzaIngredientFactory {
    public Cheese createCheese() {
        return new ReggianoCheese();
    }
    public Clams createClam() {
        return new FreshClams();
    }

    public Dough createDough() {
        return new ThinCrustDough();
    }
    public Pepperoni createPepperoni() {
        return new SlicedPepperoni();
    }
    public Sause createSauce() {
        return new MarinaraSauce();
    }

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

抽象的产品
Pizza接口

javapublic abstract class Pizza {
    String name;
    Dough dough;
    Sause sauce;
    Veggies veggies[];
    Cheese cheese;
    Pepperoni pepproni;
    Clams clam;

    abstract public void prepare();
    public void bake(){
        System.out.println("Bake for 25 mins at 350");
    }

    public void cut(){
        System.out.println("Cutting the pizza into diagonal slics");
    }
    public void box(){
        System.out.println("Place pizza in official PizzaStore box");
    }
    public String getName(){
        return name;
    }
    public void setName(String name){
         this.name = name;
    }
}

具体的产品CheesePizza:使用了(组合)抽象工厂生产的一组产品,集合起来的产品为CheesePizza

javapublic class CheesePizza extends Pizza {
    PizzaIngredientFactory ingredientFactory; // 要制作pizza,需要提供原料,所以每个pizza都需要从构造器参数得到一个工厂

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

    }
}

客户的代码只需要涉及抽象工厂

javapublic class NYPizzaStore extends PizzaStore {
    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");
        }
        return pizza;
    }
}

工厂模式 VS 抽象工厂模式

都负责封装对象的创建。都能将对象的创建封装起来,将应用程序解耦,并降低对其特定实现的依赖。

工厂模式使用的是类,通过继承,即利用工厂方法创建对象,需要扩展一个类,并覆盖它的工厂方法。

工厂模式提供一个抽象的接口来创建一个产品,由每个子类决定实例化哪个具体的产品(具体类)

而抽象工厂模式使用的是对象,使用组合。即提供一个用来创建一个产品家族的抽象类型,这个类型的子类定义了产品被产生的方法。要使用这个工厂,必须先实例化它,然后将它传入一些针对抽象类型所写的代码里。

抽象工厂模式提供一个抽象接口来创建一个产品家族,每个具体子类都创建一个家族产品。