Java设计模式之工厂模式

需求说明

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

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

传统写法

Pizza.java

复制代码
public abstract class Pizza {

    public abstract void prepare();

    private String name;

    public String getName() {
        return name;
    }

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

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

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

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

}

奶酪披萨

复制代码
public class CheesePizza extends Pizza {
    @Override
    public void prepare() {
        System.out.println("给制作奶酪披萨准备原材料");
    }
}

希腊披萨

复制代码
public class GreekPizza extends Pizza {
    @Override
    public void prepare() {
        System.out.println("给制作希腊披萨准备原材料");
    }
}

披萨订购

复制代码
public class OrderPizza {

    public OrderPizza() {
        Pizza pizza = null;
        String orderType;
        do {
            orderType = 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.bake();
            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 "";
        }
    }
}

披萨店

复制代码
public class PizzaStore {
    public static void main(String[] args) {
        new OrderPizza();
    }
}

这样就能根据输入的披萨种类,来制作对应的披萨

输出如下

复制代码
input pizza type:
cheese
给制作奶酪披萨准备原材料
奶酪披萨 baking
奶酪披萨 cutting
奶酪披萨 boxing
input pizza type:
greek
给制作希腊披萨准备原材料
希腊披萨 baking
希腊披萨 cutting
希腊披萨 boxing
input pizza type:
hello

Process finished with exit code 0

这种写法的优点是比较好理解,简单易操作,但是缺点是违反了设计模式的ocp原则,即对扩展开发,对修改关闭。比如我们要增加一个新的Pizza种类,就需要修改OrderPizza中的代码,如果有好多个

简单工厂模式

针对上面写法的缺点进行改造,把创建Pizza对象封装到一个类中,这样我们有新的Pizza种类时,只需要修改该类即可,其他有创建Pizza对象的代码就不需要修改了 -> 简单工程模式。

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

工厂类

复制代码
public class SimpleFactory {
    public Pizza createPizza(String type) {
        Pizza pizza = null;
        System.out.println("使用简单工厂模式");

        if (type.equals("greek")) {
            pizza = new GreekPizza();
            pizza.setName("希腊披萨");
        } else if (type.equals("cheese")) {
            pizza = new CheesePizza();
            pizza.setName("奶酪披萨");
        } else if (type.equals("pepper")){
            pizza = new PepperPizza();
            pizza.setName("胡椒披萨");
        } else {
            pizza = null;
        }
        return pizza;
    }

}

披萨订购类

复制代码
public class OrderPizza {

    private SimpleFactory factory;

    private Pizza pizza;

    public OrderPizza(SimpleFactory factory) {
        this.factory = factory;
        String orderType = "";
        do {
            orderType = getType();
            pizza = this.factory.createPizza(orderType);
            if (pizza != null) {
                pizza.prepare();
                pizza.bake();
                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 "";
        }
    }
}

披萨店

复制代码
public class PizzaStore {
    public static void main(String[] args) {
        // 使用简单工厂模式
        new OrderPizza(new SimpleFactory());
        System.out.println("退出了程序");
    }
}

静态工厂模式

简单工厂模式也叫静态工厂模式,原因是创建对象的方法可以写成一个静态方法。将上面的代码做如下修改

SimpleFactory增加一个方法:

复制代码
    public static Pizza createPizza2(String type) {
        Pizza pizza = null;
        System.out.println("使用静态工厂模式");

        if (type.equals("greek")) {
            pizza = new GreekPizza();
            pizza.setName("希腊披萨");
        } else if (type.equals("cheese")) {
            pizza = new CheesePizza();
            pizza.setName("奶酪披萨");
        } else if (type.equals("pepper")){
            pizza = new PepperPizza();
            pizza.setName("胡椒披萨");
        } else {
            pizza = null;
        }
        return pizza;
    }

OrderPizza2

复制代码
public class OrderPizza2 {


    private Pizza pizza;

    public OrderPizza2() {
        String orderType = "";
        do {
            orderType = getType();
            // 直接使用类名调用
            pizza = SimpleFactory.createPizza2(orderType);
            if (pizza != null) {
                pizza.prepare();
                pizza.bake();
                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 "";
        }
    }
}

披萨店

复制代码
public class PizzaStore {
    public static void main(String[] args) {
        // 使用静态工厂模式
        new OrderPizza2();
        System.out.println("退出了程序");
    }
}

效果是一样的

工厂方法模式

假如有了新的需求:

客户在点披萨时,可以点不同的口味,比如北京的奶酪pizza、北京的胡椒pizza或者伦敦的奶酪pizza、伦敦的胡椒pizza

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

北京奶酪披萨

复制代码
public class BJCheesePizza extends Pizza {
    @Override
    public void prepare() {
        setName("北京奶酪");
        System.out.println("为北京的奶酪披萨准备材料");
    }
}

北京胡椒披萨

复制代码
public class BJPepperPizza extends Pizza {
    @Override
    public void prepare() {
        setName("北京胡椒");
        System.out.println("为北京的胡椒披萨准备材料");
    }
}

伦敦奶酪披萨

复制代码
public class LDCheesePizza extends Pizza {
    @Override
    public void prepare() {
        setName("伦敦奶酪");
        System.out.println("为伦敦的奶酪披萨准备材料");
    }
}

伦敦胡椒披萨

复制代码
public class LDPepperPizza extends Pizza {
    @Override
    public void prepare() {
        setName("伦敦胡椒");
        System.out.println("为伦敦的胡椒披萨准备材料");
    }
}

OrderPizza

复制代码
public abstract class OrderPizza {



    public abstract Pizza createPizza(String orderType);

    public OrderPizza() {
        Pizza pizza = null;
        String orderType = "";
        do {
            orderType = getType();
            pizza = createPizza(orderType);
            if (pizza != null) {
                pizza.prepare();
                pizza.bake();
                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 "";
        }
    }
}

其中createPizza()这个抽象方法由子类去实现

北京OrderPizza

复制代码
public class BJOrderPizza extends OrderPizza {
    @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;
    }
}

伦敦OrderPizza

复制代码
public class LDOrderPizza extends OrderPizza {
    @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;
    }
}

PizzaStore

复制代码
public class PizzaStore {
    public static void main(String[] args) {
        // 工厂方法模式:定一个创建对象的抽象方法,由子类决定要实例化的类,工厂方法模式将对象的实例化推迟到子类
        String location = "bj";
        if (location.equals("bj")) {
            // 创建北京口味的各种披萨
            new BJOrderPizza();
            System.out.println("退出了程序");
        } else if (location.equals("ld")) {
            // 创建伦敦口味的各种披萨
            new LDOrderPizza();
            System.out.println("退出了程序");
        }
    }
}

抽象工厂模式

抽象工厂模式将工厂抽象成两层,AbsFactory(抽象工厂)和具体实现的工厂子类,程序员可以根据创建对象类型使用对象的工厂子类,这样将单个的简单工厂变成工厂簇,更利于代码的维护和扩展。

抽象工厂

复制代码
public interface AbsFactory {
    Pizza createPizza(String orderType);
}

北京披萨工厂

复制代码
public class BJFactory implements AbsFactory {
    @Override
    public Pizza createPizza(String orderType) {
        System.out.println("使用的是抽象工厂模式");
        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) {
        System.out.println("使用的是抽象工厂模式");
        Pizza pizza = null;
        if (orderType.equals("cheese")) {
            pizza = new LDCheesePizza();
        } else if (orderType.equals("pepper")) {
            pizza = new LDPepperPizza();
        }
        return pizza;
    }
}

OrderPizza

复制代码
public class OrderPizza {


    private AbsFactory factory;

    public OrderPizza(AbsFactory factory) {
        this.factory = factory;

        Pizza pizza = null;
        String orderType = "";
        do {
            orderType = getType();
            pizza = this.factory.createPizza(orderType);
            if (pizza != null) {
                pizza.prepare();
                pizza.bake();
                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 "";
        }
    }
}

PizzaStore

复制代码
public class PizzaStore {
    public static void main(String[] args) {
        // 抽象工厂模式:
        // 将工厂抽象成两层,抽象工厂和具体实现的工厂子类
        new OrderPizza(new BJFactory());
    }
}

小结

代码地址:
https://github.com/mundane799699/DesignPattern/tree/master/FactoryDesignPattern

参考:
尚硅谷Java设计模式(图解+框架源码剖析)
© 著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务

喜欢的朋友记得点赞、收藏、关注哦!!!

相关推荐
SamDeepThinking14 分钟前
我们当年是如何真实落地BFF的?
java·后端·架构
码语智行16 分钟前
Shapefile获取空间数据和中心点坐标
java·arcgis
caoyc16 分钟前
RAG 赛道全景扫描:ragflow 一骑绝尘、微软谷歌跟进乏力、下半场属于 Agent
java
如果超人不会飞20 分钟前
TinyRobot SuggestionPills紧凑的建议按钮组组件
前端·vue.js
Asmewill21 分钟前
Centos系统docker时间同步方案
后端
如果超人不会飞22 分钟前
TinyRobot Container构建优雅的AI对话容器
前端·vue.js
屋外雨大,惊蛰出没29 分钟前
深入浅出Spring Boot
java·spring boot·ioc·aop
用户83562907805130 分钟前
使用 Python 操作 Word 评论和回复
后端·python
如果超人不会飞34 分钟前
TinyRobot SuggestionPopover智能建议弹出框组件
前端·vue.js