设计模式学习笔记(7):工厂模式(3)

       接下来,我们来说下抽象工厂模式。

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

      在这里我们可以看到这里指的“家族”,这是区别于普通工厂模式应用上比较大的差别。在一般的应用场景里,家族都指的是生产过程中有一定关联的产品,例如:pizza店里面的原料制作。

       在前例中,因为各地加盟店开张,我们需要因地制宜地调整pizza的原料。纽约的Pizza用到的原料是大蒜番茄酱料,Reggiano干酪以及新鲜的蛤蜊……而芝加哥的Pizza用到的是不同的原料。我们可以看到Pizza依赖于这种原料家族,并且原料之间拥有相关性。

        我们先设计一个接口,用来生产各种原料。

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 new Veggies[0];
    }

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

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

public class ChicagoIngredientFactory implements PizzaIngredientFactory {
    @Override
    public Dough createDough() {
        return new ThickCrustDough();
    }

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

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

    @Override
    public Veggies[] createVeggies() {
        Veggies veggies[] = {new BlackOlives(),new Spinach(),new EggPlant() };
        return veggies;
    }

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

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

原料准备好了,我们现在要去做Pizza了

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;
    //要制作Pizza,需要工厂提供原料,所以每个Pizza类都需要从构造器参数中得到一个工厂,并把这个工厂存储到一个实例变量中去
    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();
        clams = ingredientFactory.createClam();
    }
}
最后我们保证各地的Store能够跟IngredientFactory挂上钩,这样就完成了
public class NYPizzaStore extends PizzaStore {
    @Override
    Pizza createPizza(String type) {
        Pizza pizza = null;
        PizzaIngredientFactory ingredientFactory = new NYPizzaIngredientFactory();
        if (type.equals("cheese")){
            pizza = new CheesePizza(ingredientFactory);
            pizza.setName("New York Style Cheese Pizza");
        }else if (type.equals("clam")){
            pizza = new ClamPizza(ingredientFactory);
        }
        return pizza;
    }
}


在抽象工厂中,我们引入了新类型的工厂,来创建Pizza原料家族。通过抽象工厂所提供的接口,可以创建产品的家族,利用这个接口书写代码避免了在上下文中出现各式各样的工厂(CheeseFactory,ClamsFactory……),实现了“解耦”。


接下来我们来详细比较一下抽象工厂和普通工厂的差异:

1.普通工厂通过生产类的子类来创建对象,用这种做法,客户只需要知道他们所使用的抽象类型就可以了,而由子类去决定具体类型。

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

2.普通工厂一般使用继承,抽象工厂使用的是对象的组合。

3.最明显的差异是抽象工厂是用来创建产品家族的。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值