设计模式--抽象工厂方法和工厂方法

定义

工厂方法模式定义了一个创建对象的接口,但由子类决定要实例化的类是哪一个。工厂方法让类把实例化推迟到子类。

抽象工厂模式提供一个接口,用于创建相关或依赖对象的家族,而不需要明确指定具体类。
抽象工程模式类图
从PizzaStore的角度,来理解上面的这个类图:
PizzaStore
抽象工厂的任务是,定义一个创建一组产品的接口。这个接口内的每个方法都负责创建一组产品。同时,我们利用实现抽象工厂的子类来提供这些具体的做法。
我们来看一个例子

/**
 * @author ZerlindaLi create at 2019/8/15 15:15
 * @version 1.0.0
 * @description PizzaIngredientFactory
 * 开始先为工厂定义一个接口,这个接口负责创建所有的原料
 */
public interface PizzaIngredientFactory {
    public Dough createDough();

    public Sauce createSauce();

    public Cheese createCheese();

    public Veggies[] createVeggies();

    public Pepperoni createPepperoni();

    public Clams createClam();
}
/**
 * @author ZerlindaLi create at 2019/8/15 15:30
 * @version 1.0.0
 * @description NYPizzaIngredientFactory
 * 这是纽约原料工厂的实现。这工厂专精于大蒜番茄酱料、Reggiano干酪、新鲜哈利···
 * 具体原料工厂必须实现PizzaIngredientFactory这个接口,纽约原料工厂也不例外
 */
public class NYPizzaIngredientFactory implements PizzaIngredientFactory {

    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();
    }
}
/**
 * @author ZerlindaLi create at 2019/8/12 16:49
 * @version 1.0.0
 * @description 抽象PizzaStore 创建者类
 * 这是抽象创建者类,它定义了一个抽象的工厂方法,让子类实现此方法制造产品
 * 创建者通常会包含依赖于抽象产品的代码,而这些抽象产品由子类制造。创建者不需要真的知道在制造哪种具体产品。
 */
public abstract class PizzaStore {
    public Pizza orderPizza(String type) {
        Pizza pizza;

        // createPizza()方法从工厂对象中移回PizzaStore
        pizza = createPizza(type);

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

        return pizza;
    }

    // 现在把工厂对象移到这个方法中,现在是抽象的
    abstract Pizza createPizza(String  type);
}

/**
 * @author ZerlindaLi create at 2019/8/13 16:04
 * @version 1.0.0
 * @description NYPizzaStore 能够产生产品的类成为具体创建者
 */
public class NYPizzaStore extends PizzaStore{
    /**
     * 此方法正是工厂方法,用来制造产品。
     * 因为每个加盟店都有自己的PizzaStore子类,所以可以用实现createPizza()创建自己风味的披萨
     * @param item
     * @return
     */
    protected 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;
    }
}
/**
 * @author ZerlindaLi create at 2019/8/13 15:00
 * @version 1.0.0
 * @description Pizza 工厂生产产品。对PizzaStore来说,产品就是Pizza.
 */
public abstract class Pizza {

    // 每个披萨都持有一组在准备时会用到的原料
    String name;

    Dough dough;

    Sauce sauce;

    Veggies veggies[];

    Cheese cheese;

    Pepperoni pepperoni;

    Clams clam;

    // 现在把prepare()方法声明成抽象。在这个方法中,我们需要收集披萨所需的原料,而这些原料当然是来自原料工厂了。
    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");
    }

    public String getName(){
        return name;
    }

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

    public String toString() {
        // 这里是打印披萨的代码
        return name;
    }
}

public class ClamPizza extends Pizza {

    PizzaIngredientFactory ingredientFactory;

    public ClamPizza(PizzaIngredientFactory ingredientFactory) {
        // 蛤蜊披萨也需要原料工厂
        this.ingredientFactory = ingredientFactory;
    }

    @Override
    void prepare() {
        System.out.println("Preparing " + name);
        // 要做出蛤蜊披萨,prepare()方法就必须从本地工厂中取得正确的原料。
        dough = ingredientFactory.createDough();
        sauce = ingredientFactory.createSauce();
        cheese = ingredientFactory.createCheese();
        // 如果是纽约工厂,就会使用新鲜的蛤蜊,如果是芝加哥工厂,就是冷冻的蛤蜊
        clam = ingredientFactory.createClam();
    }
}
public class VeggiePizza extends Pizza {

    PizzaIngredientFactory pizzaIngredientFactory;

    public VeggiePizza(PizzaIngredientFactory pizzaIngredientFactory) {
        this.pizzaIngredientFactory = pizzaIngredientFactory;
    }
    @Override
    void prepare() {
        System.out.println("Preparing " + name);
        // 神奇的事情发生在这里!
        // prepare()方法一步一步地创建芝士披萨,每当需要原料时,就更工厂要。
        dough = pizzaIngredientFactory.createDough();
        sauce = pizzaIngredientFactory.createSauce();
        cheese = pizzaIngredientFactory.createCheese();
    }
}

下面请看原材料

public interface Dough {
}
public class ThinCrustDough implements Dough {
}
public interface Sauce {
}

public class MarinaraSauce implements Sauce {
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Zerlinda_Li

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值