美文网首页
Java设计模式之工厂模式

Java设计模式之工厂模式

作者: mundane | 来源:发表于2021-03-14 21:48 被阅读0次

    需求说明

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

    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设计模式(图解+框架源码剖析)

    相关文章

      网友评论

          本文标题:Java设计模式之工厂模式

          本文链接:https://www.haomeiwen.com/subject/duxtcltx.html