一、 简介

工厂方法模式是一种 创建模式,该模式使用工厂方法来处理创建对象的问题,而不必指定将要创建的对象的确切类。这是通过调用工厂方法(而不是通过构造函数)来创建对象的,该工厂方法是在接口中指定并由子类实现,或者在基类中实现,并且可以选择由派生类覆盖。

 

二、工作模式的N种方式

我们从一个简单的披萨项目入手,项目需要满足三个需求:

a、披萨的种类很多(比如 GreekPizz、CheesePizz 等) b、披萨的制作有 prepare,bake, cut, box c、完成披萨店订购功能

1、原始方法

类图

 

案例

1、定义一个抽象类,完成披萨的制作过程

package com.ycdhz.design.factory.simplefactory;

public abstract class Pizza {

    private String pizzaType;

    public abstract void prepare();

    public void bake() {
        System.out.println("bake");
    }

    public void cut() {
        System.out.println("cut");
    }

    public void box() {
        System.out.println("box");
    }

    public void setPizzaType(String pizzaType) {
        this.pizzaType = pizzaType;
    }
}

2、不同的Pizza 类型去继承Pizza 的抽象类

package com.ycdhz.design.factory.simplefactory;

public class CheesePizza extends Pizza {

    @Override
    public void prepare() {
        System.out.println("制作奶酪披萨的原材料");
    }
}

public class ChickenPizza extends Pizza {

    @Override
    public void prepare() {
        System.out.println("制作鸡肉披萨的原材料");
    }
}

3、定制一个类,来专门的定制Pizza

package com.ycdhz.design.factory.simplefactory;

public class OrderPizza {

    public void getOrderPizza(String type){
        Pizza pizza = null;

        if(type.equals("cheese")){
            pizza = new CheesePizza();
            pizza.setPizzaType(type);
        } else if (type.equals("chicken")){
            pizza = new ChickenPizza();
            pizza.setPizzaType(type);
        } else {
            System.out.println(type + "以售尽");
        }

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

4、 模拟一个客户端,例如 开一个新的Pizza 店,调用OrderPizza

package com.ycdhz.design.factory.simplefactory;

public class PizzaStore {

    public static void main(String[] args) {
        OrderPizza orderPizza = new OrderPizza();
        orderPizza.getOrderPizza("cheese");
    }
}

 

2、简单工厂

每一个Pizza 店铺,都可能有一个对应的OrderPizza 类,如果说我们更新了Pizza 的类型,必然会对所有的OrderPizza 类进行一个修改。 我们可以把创建 Pizza 对象封装到一个类中,这样我们有新的 Pizza 种类时只需要修改该类就可,其它有创建到 Pizza 对象的代码就不需要修改了。

类图

 

案例

1、 从OrderPizza 中将createPizza 提取出来,形成SimplePizzaFactory

package com.ycdhz.design.factory.simplefactory;

public class SimplePizzaFactory {

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

        if(type.equals("cheese")){
            pizza = new CheesePizza();
        } else if (type.equals("chicken")) {
            pizza = new ChickenPizza();
        } else {
            return pizza;
        }
        return pizza;
    }
}

 2、 定制Pizza 过程,通过构造方法来实例化 SimplePizzaFactory

package com.ycdhz.design.factory.simplefactory;

public class OrderPizza {

    SimplePizzaFactory simpleFactory;

    public OrderPizza(SimplePizzaFactory simpleFactory) {
        this.pizzaType = pizzaType;
    }

    public void orderPizza(String type) {

        Pizza pizza = this.simpleFactory.createPizza(type);

        if(pizza != null) {
            pizza.prepare();
            pizza.bake();
            pizza.cut();
            pizza.box();
        } else {
            System.out.println(" 订购披萨失败 ");
        }
    }
}

3、模拟一个客户端,调用OrderPizza

package com.ycdhz.design.factory.simplefactory;

public class PizzaStore {

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

总结:简单工厂模式是属于 创建型模式,是工厂模式的一种。简单工厂模式是由一个工厂对象决定创建出哪一种产品 类的实例。

 

3、工厂方法

随着用户数量的增加,客户群体也在不断的变换。客户对披萨口味有更多的要求,比如北京的奶酪 pizza、北京的胡椒 pizza 或者是伦敦的奶酪 pizza、伦敦的胡椒 pizza。如果是简单工厂方式,我们可以通过新增ZHSimplePizzaFactory、NYSimplePizzaFactory 来进行解决。但考虑到项目的可维护性,我们可以将项目中实例化功能抽象成抽象方法,放到子类中去完成。

类图

案例

1、 修改OrderPizza 类, 将createPizza 交给子类来完成

public abstract class OrderPizza {

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

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

    public abstract Pizza createPizza(String type);
}

2、定义一个ZHOrderPizza 来完成中国口味的pizza 的

public class ZHOrderPizza extends OrderPizza {

    @Override
    public Pizza createPizza(String type) {
        Pizza pizza = null;
        if(type.equals("cheese")){
            pizza = new ZHCheesePizza();
        } else if (type.equals("chicken")) {
            pizza = new ZHChickenPizza();
        } else {
            System.out.println("not pizza");
        }
        return pizza;
    }
}

3、模拟一个客户端,调用OrderPizza

public class PizzaStore {

    public static void main(String[] args) {
        OrderPizza pizzaStore = new ZHOrderPizza();
        pizzaStore.orderPizza("cheese");
    }
}

总结:定义了一个创建对象的抽象方法,由子类决定要实例化的类。工厂方法模式将对象的实例化推迟到子类。

 

4、抽象工厂

随着加盟店铺的增加,我们需要对pizza 的原料进行统一处理。 这个时候我们需要为每个区域建造一个工厂并继承自PizzaIngredientFactory。同时要实现一组原料类供工厂使用。

类图

案例

1、 创建一组原料类

public class Dough {}

public class Sauce {}

2、 创建一个原料接口

public interface PizzaIngredientFactory {

    public Dough createDough();

    public Sauce createSauce();
}

3、创建一个纽约的原材料类实现原料接口

package com.ycdhz.design.factory.factorydesign;

public class NYPizzaIngredientFactory implements PizzaIngredientFactory {

    @Override
    public Dough createDough() {
        System.out.println("NY pizza Dough");
        return null;
    }

    @Override
    public Sauce createSauce() {
        System.out.println("NY pizza Sauce");
        return null;
    }
}

4、 创建一个Pizza 类

public abstract class Pizza {

    public Dough dough;

    public Sauce sauce;

    protected abstract void prepare();

    public void bake() {
        System.out.println("bake");
    }

    public void cut() {
        System.out.println("cut");
    }

    public void box() {
        System.out.println("box");
    }

    public Dough getDough() {
        return dough;
    }

    public void setDough(Dough dough) {
        this.dough = dough;
    }

    public Sauce getSauce() {
        return sauce;
    }

    public void setSauce(Sauce sauce) {
        this.sauce = sauce;
    }
}

5、根据不同种类的Pizza 去继承Pizza 类

public class CheesePizza extends Pizza {

    PizzaIngredientFactory ingredientFactory;

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

    @Override
    public void prepare() {
        this.dough = ingredientFactory.createDough();
        this.sauce = ingredientFactory.createSauce();
    }
}

6、 通过OrderPizza 进行组装

public abstract class OrderPizza {

    protected Pizza orderPizza(String type){
        Pizza pizza = createPizza(type);

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

    protected abstract Pizza createPizza(String type);
}
public class NYOrderPizza extends OrderPizza {

    @Override
    protected Pizza createPizza(String type) {
        Pizza pizza = null;
        PizzaIngredientFactory factory = new NYPizzaIngredientFactory();

        if(type.equals("cheese")){
            pizza = new CheesePizza(factory);
        } else if (type.equals("chicken")) {
            pizza = new ChickenPizza(factory);
        } else {
            System.out.println("没有当前品种的pizza");
            return null;
        }

        return pizza;
    }
}

4、模拟一个客户端,调用OrderPizza

public class PizzaStore {

    public static void main(String[] args) {
        OrderPizza pizzaStore = new NYOrderPizza();
        pizzaStore.orderPizza("cheese");
    }
}

总结:抽象工厂模式:定义了一个 interface 用于创建相关或有依赖关系的对象簇,而无需指明具体的类。从设计层面看,抽象工厂模式就是对简单工厂模式的改进(或者称为进一步的抽象)。将工厂抽象成两层,OrderPizza( 抽象工厂) 和 具体实现的工厂子类。程序员可以根据创建对象类型使用对应的工厂子类。这样将单个的简单工厂类变成了工厂簇,更利于代码的维护和扩展。

 

posted on 2020-08-10 09:53  愚蠢的猴子  阅读(223)  评论(0编辑  收藏  举报