设计模式之工厂模式详解

文章目录

    • 前言
    • 1 用传统方式来完成
      • 1.1 步骤实现
      • 1.2 优缺点
    • 2 简单工厂模式
      • 2.1 简单工厂模式
      • 2.2 步骤实现
    • 3 工厂方法模式
      • 3.1 工厂方法模式介绍
      • 3.2 步骤实现
    • 4 抽象工厂模式
      • 4.1 抽象工厂模式介绍
      • 4.2 步骤实现
    • 5 工厂模式小结
      • 5.1 工厂模式意义:
      • 5.2 三种工厂模式:
      • 5.3 设计模式的依赖抽象原则:

前言

一个披萨的项目:要便于披萨种类的扩展,要便于维护

  1. 披萨的种类很多(比如GreekPizza、CheesePizza等)
  2. 披萨的之作有prepare,bake,cut,box
  3. 完成披萨店订购功能

1 用传统方式来完成

1.1 步骤实现

  1. 相关类图如下:
    设计模式之工厂模式详解_第1张图片

设计模式之工厂模式详解_第2张图片

  1. 新建pizza类,将Pizza类做成抽象
public abstract class Pizza {

    /**
     * 名字
     */
    protected String name;

	// 准备原材料,不同的披萨不一样,因此我们做成抽象方法
    public abstract void prepare();

    public void back() {
        System.out.println(name + "baking;");
    }

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

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

    public void setName(String name) {
        this.name = name;
    }
    
}
  1. 新建CheesePizza类和GreekPizza类,并继承pizza类
public class CheesePizza extends Pizza {

    @Override
    public void prepare() {
        System.out.println("给奶酪披萨准备原材料");
    }
}

public class GreekPizza extends Pizza {
    
    @Override
    public void prepare() {
        System.out.println("给希腊披萨准备原材料");
    }
}
  1. 新建OrderPizza类,用于订购披萨
public class OrderPizza {

    /**
     * 构造器
     */
    public OrderPizza() {
        Pizza pizza = null;
        // 订购披萨的类型
        String orderType;
        do {
            orderType = this.getType();
            if (orderType.equals("greek")) {
                pizza = new GreekPizza();
                pizza.setName("希腊披萨");
            } else if (orderType.equals("cheese")) {
                pizza = new CheesePizza();
                pizza.setName("奶酪披萨");
            } else {
                break;
            }
            // 输出披萨的制作过程
            pizza.prepare();
            pizza.back();
            pizza.cut();
            pizza.box();
        } while (true);
    }

    private String getType() {
        try {
            BufferedReader strin = new BufferedReader(new InputStreamReader(System.in));
            System.out.println("input pizza type:");
            String str = strin.readLine();
            return str;
        } catch (IOException e){
            e.printStackTrace();
            return "";
        }
    }

}

  1. 新建PizzaStore类,用于生成披萨
public class PizzaStore {

    public static void main(String[] args) {
        new OrderPizza();
    }

}

1.2 优缺点

  1. 优点是比较好理解,简单易操作。
  2. 缺点是违反了设计模式的ocp原则,即对扩展开放,对修改关闭。即当我们给类增加新功能时,尽量不修改代码,或者尽可能少修改代码。
  3. 当我们需要新增加一个种类,则需要对代码进行修改。
  4. 改进的思路分析:把创建pizza对象封装到一个类中,这样我们有新的pizza种类时,只需要修改该类就可以,其他有创建到pizza对象的代码就不需要修改了,即简单工厂模式

2 简单工厂模式

2.1 简单工厂模式

  1. 简单工厂模式是属于创建型模式,是工厂模式的一种。简单工厂模式是由一个工厂对象决定创建出哪一种产品类的实例。简单工厂模式是工厂模式家族中最简单实用的模式
  2. 简单工厂模式:定义了一个创建对象的类,由这个类来封装实例化对象的行为;
  3. 在软件开发中,当我们会用到大量的创建某种、某类或者某批对象时,就会使用到工厂模式。

2.2 步骤实现

简单工厂模式的设计方案:定义一个可以实例化Pizza对象的类,封装创建对象的代码
  1. 创建简单工厂类SimpleFactory
// 创建简单工厂类
public class SimpleFactory {

    // 增加orderType,返回对应的pizza对象
    public Pizza createPizza(String orderType) {

        Pizza pizza = null;

        System.out.println("使用简单工厂模式");
        if (orderType.equals("greek")) {
            pizza = new GreekPizza();
            pizza.setName("希腊披萨");
        } else if (orderType.equals("cheese")) {
            pizza = new CheesePizza();
            pizza.setName("奶酪披萨");
        }else if (orderType.equals("pepper")) {
            pizza = new CheesePizza();
            pizza.setName("胡椒披萨");
        }

        return pizza;
    }

}
  1. 修改OrderPizza的实现
public class OrderPizza {

    // 定义一个简单工厂对象
    SimpleFactory simpleFactory;
    Pizza pizza = null;

    // 构造器
    public OrderPizza(SimpleFactory simpleFactory) {
        setFactory(simpleFactory);
    }



    public void setFactory(SimpleFactory simpleFactory) {
        String orderType = "";

        // 设置简单工厂模式
        this.simpleFactory = simpleFactory;

        do {
            orderType = getType();
            pizza = this.simpleFactory.createPizza(orderType);

            // 输出pizza
            if(pizza != null) {
                // 订购成功
                pizza.prepare();
                pizza.back();
                pizza.cut();
                pizza.box();
            }else {
                System.out.println("订购披萨失败");
                break;
            }
        }while (true);
    }

    private String getType() {
        try {
            BufferedReader strin = new BufferedReader(new InputStreamReader(System.in));
            System.out.println("input pizza type:");
            String str = strin.readLine();
            return str;
        } catch (IOException e){
            e.printStackTrace();
            return "";
        }
    }
}
  1. 修改PizzaStore的实现
public class PizzaStore {

    public static void main(String[] args) {
        // new OrderPizza();

        // 使用简单工厂模式
        new OrderPizza(new SimpleFactory());

    }

}

3 工厂方法模式

3.1 工厂方法模式介绍

  1. 工厂方法模式设计方案: 将披萨项目的实例化功能抽象成抽象方法,在不同的口味点餐子类中具体实现。
  2. 工厂方法模式: 定义了一个创建对象的抽象方法,由子类决定要实例化的类。工厂方法模式将 对象的实例化推迟到子类

3.2 步骤实现

  1. 相关类图如下所示:
    设计模式之工厂模式详解_第3张图片
  2. 新建pizza类
// 将Pizza类做成抽象

public abstract class Pizza {

    /**
     * 名字
     */
    protected String name;

    // 准备原材料,不同的披萨不一样,因此我们做成抽象方法
    public abstract void prepare();

    public void back() {
        System.out.println(name + "baking;");
    }

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

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

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

}
  1. 分别创建LDCheesePizza、LDpepperPizza、BJCheesePizza、BJpepperPizza,并继承pizza类
public class LDCheesePizza extends Pizza {
    @Override
    public void prepare() {
        setName("伦敦的奶酪pizza");
        System.out.println("伦敦的胡奶酪pizza 准备原材料");
    }
}

public class LDpepperPizza extends Pizza {
    @Override
    public void prepare() {
        setName("伦敦的胡椒pizza");
        System.out.println("伦敦的胡椒pizza 准备原材料");
    }
}

public class BJCheesePizza extends Pizza {
    @Override
    public void prepare() {
        setName("北京的奶酪pizza");
        System.out.println("北京的奶酪pizza 准备原材料");
    }
}

public class BJpepperPizza extends Pizza {
    @Override
    public void prepare() {
        setName("北京的胡椒pizza");
        System.out.println("北京的胡椒pizza 准备原材料");
    }
}
  1. 新建抽象类OrderPizza
public abstract class OrderPizza {

    // 定义一个抽象方法,createPizza,让各个工厂子类自己实现
    abstract Pizza createPizza(String orderType);

    // 构造器
    public OrderPizza() {
        Pizza pizza = null;
        // 订购披萨类型
        String orderType;
        do {
            orderType = getType();
            // 抽象方法,由工厂子类完成
            pizza = createPizza(orderType);
            // 输出pizza制作过程
            pizza.prepare();
            pizza.back();
            pizza.cut();
            pizza.box();
        }while (true);
    }

    private String getType() {
        try {
            BufferedReader strin = new BufferedReader(new InputStreamReader(System.in));
            System.out.println("input pizza type:");
            String str = strin.readLine();
            return str;
        } catch (IOException e){
            e.printStackTrace();
            return "";
        }
    }

}

  1. 分别创建BJOrderPizza、LDOrderPizza并继承OrderPizza
public class BJOrderPizza extends OrderPizza {
    @Override
    Pizza createPizza(String orderType) {
        Pizza pizza = null;
        if(orderType.equals("cheese")) {
            pizza = new BJCheesePizza();
        }else if(orderType.equals("pepper")) {
            pizza = new BJpepperPizza();
        }
        return pizza;
    }
}

public class LDOrderPizza extends OrderPizza {
    @Override
    Pizza createPizza(String orderType) {
        Pizza pizza = null;
        if(orderType.equals("cheese")) {
            pizza = new LDCheesePizza();
        }else if(orderType.equals("pepper")) {
            pizza = new LDpepperPizza();
        }
        return pizza;
    }
}
  1. 创建PizzaStore类
public class PizzaStore {

    public static void main(String[] args) {
        // 创建北京的各种口味披萨
        // new BJOrderPizza();
        // 创建伦敦的各种口味披萨
        new LDOrderPizza();
    }

}

4 抽象工厂模式

4.1 抽象工厂模式介绍

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

4.2 步骤实现

  1. 相关类图如下所示:
    设计模式之工厂模式详解_第4张图片
  2. 一个抽象工厂模式的抽象层(接口)AbsFactory
// 一个抽象工厂模式的抽象层(接口)
public interface AbsFactory {

    // 让下面的工厂子类来具体实现
    public Pizza createPizza(String orderType);

}
  1. 定义工厂子类BJFactory、LDFactory并实现AbsFactory
public class BJFactory implements AbsFactory {
    @Override
    public Pizza createPizza(String orderType) {
        Pizza pizza = null;
        if(orderType.equals("cheese")) {
            pizza = new BJCheesePizza();
        }else if(orderType.equals("pepper")) {
            pizza = new BJpepperPizza();
        }
        return pizza;
    }
}

public class LDFactory implements AbsFactory {
    @Override
    public Pizza createPizza(String orderType) {
        Pizza pizza = null;
        if(orderType.equals("cheese")) {
            pizza = new LDCheesePizza();
        }else if(orderType.equals("pepper")) {
            pizza = new LDpepperPizza();
        }
        return pizza;
    }
}
  1. 创建OrderPizza类
public class OrderPizza {

    AbsFactory factory;

    // 构造器
    public OrderPizza(AbsFactory factory) {
        setFactory(factory);
    }


    private void setFactory(AbsFactory factory) {
        Pizza pizza = null;
        String orderType = "";
        this.factory = factory;
        do {
            orderType = getType();
            pizza = factory.createPizza(orderType);
            if(pizza != null) {
                pizza.prepare();
                pizza.back();
                pizza.cut();
                pizza.box();
            }else {
                System.out.println("订购失败");
                break;
            }
        }while (true);
    }


    private String getType() {
        try {
            BufferedReader strin = new BufferedReader(new InputStreamReader(System.in));
            System.out.println("input pizza type:");
            String str = strin.readLine();
            return str;
        } catch (IOException e){
            e.printStackTrace();
            return "";
        }
    }

}
  1. 创建pizzastore
public class PizzaStore {

    public static void main(String[] args) {
        // 北京
        // new OrderPizza(new BJFactory());
        // 伦敦
        new OrderPizza(new LDFactory());
    }

}

5 工厂模式小结

5.1 工厂模式意义:

将实例化对象的代码提取出来,放到一个类中统一管理和维护,达到和主项目的依赖关系的解耦。从而提高项目的扩展和维护性。

5.2 三种工厂模式:

简单工厂模式、工厂方法模式、抽象工厂模式

5.3 设计模式的依赖抽象原则:

  1. 创建对象实例时,不要直接new类,而是把这个new类的动作放在一个工厂的方法中,并返回。
  2. 不要让类继承具体类,而是继承抽象类或者是实现interface。
  3. 不要覆盖基类中已经实现的方法。

你可能感兴趣的:(java,简单工厂模式,抽象工厂模式,工厂方法模式)