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


    我们现在需要建一个能够制作披萨的程序,这里面有不同口味的披萨,同时还有披萨的所有步骤,这里给出了四个步骤(准备,烘烤,切割,打包)。

    我们在不使用简单工厂模式的时候

    package com.factory.simplefactory.pizzastore.pizza;
    
    /**
     * 披萨抽象类
     */
    public  abstract class Pizza {
    
        /**
         * 披萨的名字
         */
        protected String name;
    
    
    
        /**
         * 准备原材料,不同的披萨需要准备的原材料是不一样的,这里最好做成抽象方法
         */
        public abstract void prepare();
    
        /**
         * 烘烤
         */
        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 String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    }
    

      

    package com.factory.simplefactory.pizzastore.pizza;
    
    public class GreekPizza extends Pizza {
        @Override
        public void prepare() {
            System.out.println("给制作希腊披萨准备原材料");
        }
    }
    

      

    package com.factory.simplefactory.pizzastore.pizza;
    
    public class CheesePizza extends Pizza {
        @Override
        public void prepare() {
            System.out.println("给制作奶酪披萨准备原材料");
        }
    }
    

      

    package com.factory.simplefactory.pizzastore.order;
    
    import com.factory.simplefactory.pizzastore.pizza.CheesePizza;
    import com.factory.simplefactory.pizzastore.pizza.GreekPizza;
    import com.factory.simplefactory.pizzastore.pizza.Pizza;
    
    import java.io.BufferedReader;
    import java.io.IOException;
    import java.io.InputStreamReader;
    
    public class OrderPizza {
        //创建一个构造器
        public OrderPizza() {
            Pizza pizza=null;
            String orderType="";//订购的披萨类型
            do {
                orderType=getType();
                if("greek".equals(orderType)){
                    pizza=new GreekPizza();
                    pizza.setName("希腊披萨");
                }else if("cheese".equals(orderType)){
                    pizza=new CheesePizza();
                    pizza.setName("奶酪披萨");
                }else {
                    break;
                }
                //输出披萨的制作过程
                pizza.prepare();
                pizza.bake();
                pizza.cut();
                pizza.box();
            }while (true);
        }
    
        //获取客户希望订购的披萨种类
        private String getType(){
            try {
                BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in));
                System.out.println("请输入您想订购的披萨种类:");
                String str = bufferedReader.readLine();
                return str;
            } catch (IOException e) {
                e.printStackTrace();
                return e.toString();
            }
        }
    }
    

      

    package com.factory.simplefactory.pizzastore.order;
    
    /**
     * 相当于一个客户端,发出订购
     */
    public class PizzaStore {
        public static void main(String[] args) {
            new OrderPizza();
        }
    }
    

      

    运行结果:

    请输入您想订购的披萨种类:
    greek
    给制作希腊披萨准备原材料
    希腊披萨 baking
    希腊披萨 cutting
    希腊披萨 boxing
    请输入您想订购的披萨种类:
    cheese
    给制作奶酪披萨准备原材料
    奶酪披萨 baking
    奶酪披萨 cutting
    奶酪披萨 boxing
    请输入您想订购的披萨种类:
    yyy
    订购披萨失败!!!
    程序运行结束
    

      

    分析一下这种方法的缺点

    假设我们订购pizza的店铺有很多(说白了,在实际项目中,订购pizza的这个功能有很多系统都在调用)当我们需要增加一种pizza的时候,就会出现OrderPizza1OrderPizza2OrderPizza3等等类都需要修改(好比是好些个订阅pizza的系统都要因为你增加了一款pizza而修改自己系统的代码),这在实际项目开发中肯定是不现实的。当然这种写法也有他的好处就是:便于理解,仅此而已。

    改进方式:把创建Pizza对象封装到一个类中,这样我们有新的Pizza种类时,只需要修改该类就可以了,其他有创建到Pizza对象的代码就不需要修改了,这就是简单工厂模式。

    简单工厂模式

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

    对上面的程序进行改进:

    package com.factory.simplefactory.pizzastore.order;
    
    import com.factory.simplefactory.pizzastore.pizza.CheesePizza;
    import com.factory.simplefactory.pizzastore.pizza.GreekPizza;
    import com.factory.simplefactory.pizzastore.pizza.PepperPizza;
    import com.factory.simplefactory.pizzastore.pizza.Pizza;
    
    /**
     * 简单工厂类
     */
    public class SimpleFactory {
        //传入orderType,返回对应的Pizza
        public Pizza createPizza(String orderType) {
            Pizza pizza = null;
            System.out.println("使用简单工厂模式");
            if ("greek".equals(orderType)) {
                pizza = new GreekPizza();
                pizza.setName("希腊披萨");
            } else if ("cheese".equals(orderType)) {
                pizza = new CheesePizza();
                pizza.setName("奶酪披萨");
            } else if("pepper".equals(orderType)){
                pizza = new PepperPizza();
                pizza.setName("胡椒披萨");
            }
            return pizza;
        }
    
    }
    

      

    package com.factory.simplefactory.pizzastore.order;
    
    import com.factory.simplefactory.pizzastore.pizza.CheesePizza;
    import com.factory.simplefactory.pizzastore.pizza.GreekPizza;
    import com.factory.simplefactory.pizzastore.pizza.Pizza;
    
    import java.io.BufferedReader;
    import java.io.IOException;
    import java.io.InputStreamReader;
    
    public class OrderPizza {
    
        SimpleFactory simpleFactory = null;
        Pizza pizza = null;
    
        //添加构造方法
        public OrderPizza(SimpleFactory simpleFactory) {
            setFactory(simpleFactory);
        }
        public void setFactory(SimpleFactory simpleFactory){
            this.simpleFactory = simpleFactory;//设置简单工厂对象
            String orderType = "";//用户输入的
            do {
                orderType = getType();
                pizza = this.simpleFactory.createPizza(orderType);
                //输出披萨的制作过程
                if (null != pizza) {
                    pizza.prepare();
                    pizza.bake();
                    pizza.cut();
                    pizza.box();
                }else {
                    System.out.println("订购披萨失败!!!");
                    break;
                }
            } while (true);
        }
    
        //获取客户希望订购的披萨种类
        private String getType() {
            try {
                BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in));
                System.out.println("请输入您想订购的披萨种类:");
                String str = bufferedReader.readLine();
                return str;
            } catch (IOException e) {
                e.printStackTrace();
                return e.toString();
            }
        }
    }
    

      

    我们再添加一个胡椒pizza

    package com.factory.simplefactory.pizzastore.pizza;
    
    public class PepperPizza extends Pizza {
        @Override
        public void prepare() {
            System.out.println("给制作胡椒披萨准备原材料");
        }
    }
    

      

    package com.factory.simplefactory.pizzastore.order;
    
    import javax.sound.midi.Soundbank;
    
    /**
     * 相当于一个客户端,发出订购
     */
    public class PizzaStore {
        public static void main(String[] args) {
            new OrderPizza(new SimpleFactory());
            System.out.println("程序运行结束");
        }
    }
    

      

    运行结果:

    请输入您想订购的披萨种类:
    greek
    使用简单工厂模式
    给制作希腊披萨准备原材料
    希腊披萨 baking
    希腊披萨 cutting
    希腊披萨 boxing
    请输入您想订购的披萨种类:
    pepper
    使用简单工厂模式
    给制作胡椒披萨准备原材料
    胡椒披萨 baking
    胡椒披萨 cutting
    胡椒披萨 boxing
    请输入您想订购的披萨种类:
    cheese
    使用简单工厂模式
    给制作奶酪披萨准备原材料
    奶酪披萨 baking
    奶酪披萨 cutting
    奶酪披萨 boxing
    请输入您想订购的披萨种类:
    yyy
    使用简单工厂模式
    订购披萨失败!!!
    程序运行结束
    

      

    简单工厂模式也叫做静态工厂模式。

    当然也可以对上面的简单工厂模式换一种静态的方式来体现。

    package com.factory.simplefactory.pizzastore.order;
    
    import com.factory.simplefactory.pizzastore.pizza.Pizza;
    
    import java.io.BufferedReader;
    import java.io.IOException;
    import java.io.InputStreamReader;
    
    public class OrderPizza2 {
    
        Pizza pizza = null;
    
        //添加构造方法
        public OrderPizza2() {
            String orderType = "";//用户输入的
            do {
                orderType = getType();
                pizza = SimpleFactory.createPizza2(orderType);
                //输出披萨的制作过程
                if (null != pizza) {
                    pizza.prepare();
                    pizza.bake();
                    pizza.cut();
                    pizza.box();
                }else {
                    System.out.println("订购披萨失败!!!");
                    break;
                }
            } while (true);
        }
    
        //获取客户希望订购的披萨种类
        private String getType() {
            try {
                BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in));
                System.out.println("请输入您想订购的披萨种类:");
                String str = bufferedReader.readLine();
                return str;
            } catch (IOException e) {
                e.printStackTrace();
                return e.toString();
            }
        }
    }
    

      

    package com.factory.simplefactory.pizzastore.order;
    
    import com.factory.simplefactory.pizzastore.pizza.CheesePizza;
    import com.factory.simplefactory.pizzastore.pizza.GreekPizza;
    import com.factory.simplefactory.pizzastore.pizza.PepperPizza;
    import com.factory.simplefactory.pizzastore.pizza.Pizza;
    
    /**
     * 简单工厂类
     */
    public class SimpleFactory {
    
        //传入orderType,返回对应的Pizza
        public static Pizza createPizza2(String orderType) {
            Pizza pizza = null;
            System.out.println("使用简单工厂模式2");
            if ("greek".equals(orderType)) {
                pizza = new GreekPizza();
                pizza.setName("希腊披萨");
            } else if ("cheese".equals(orderType)) {
                pizza = new CheesePizza();
                pizza.setName("奶酪披萨");
            } else if("pepper".equals(orderType)){
                pizza = new PepperPizza();
                pizza.setName("胡椒披萨");
            }
            return pizza;
        }
    
    }
    

      

    package com.factory.simplefactory.pizzastore.order;
    
            import javax.sound.midi.Soundbank;
    
    /**
     * 相当于一个客户端,发出订购
     */
    public class PizzaStore {
        //    public static void main(String[] args) {
    //        new OrderPizza();
    //    }
        public static void main(String[] args) {
            new OrderPizza2();
            System.out.println("程序运行结束");
        }
    }
    

      

    运行结果:

    请输入您想订购的披萨种类:
    greek
    使用简单工厂模式2
    给制作希腊披萨准备原材料
    希腊披萨 baking
    希腊披萨 cutting
    希腊披萨 boxing
    请输入您想订购的披萨种类:
    cheese
    使用简单工厂模式2
    给制作奶酪披萨准备原材料
    奶酪披萨 baking
    奶酪披萨 cutting
    奶酪披萨 boxing
    请输入您想订购的披萨种类:
    pepper
    使用简单工厂模式2
    给制作胡椒披萨准备原材料
    胡椒披萨 baking
    胡椒披萨 cutting
    胡椒披萨 boxing
    请输入您想订购的披萨种类:
    yyy
    使用简单工厂模式2
    订购披萨失败!!!
    程序运行结束
    

      

    工厂方法模式:

    看一个新的需求:客户在点披萨的时,可以点不同口味的披萨,比如北京的奶酪pizza、北京的胡椒pizza或者是伦敦的奶酪pizza、路通的胡椒pizza

    思路1;

    使用简单工厂模式,创建不同的简单工厂类,比如BJPizzaSimpleFactoryLDPizzaSimpleFactory等等,从当前这个案例来说,也是可的,但是考虑到项目的规模,以及软件的可维护性、可扩展性并不是特别好。

    思路2

    使用工厂方法模式。

    工厂方法模式:

    工厂方法模式介绍

    工厂方法模式设计方案:将披萨项目的实例化功能抽象成抽象方法,在不同的口味点餐子类中具体实现。

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

    package com.factory.factorymethod.pizzasotre;
    
    /**
     * 披萨抽象类
     */
    public  abstract class Pizza {
    
        /**
         * 披萨的名字
         */
        protected String name;
    
    
    
        /**
         * 准备原材料,不同的披萨需要准备的原材料是不一样的,这里最好做成抽象方法
         */
        public abstract void prepare();
    
        /**
         * 烘烤
         */
        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 String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    }
    

      

    package com.factory.factorymethod.pizzasotre;
    
    public class LDPepperPizza extends Pizza {
    
        @Override
        public void prepare() {
            setName("伦敦的胡椒pizza");
            System.out.println("伦敦胡椒披萨准备");
        }
    }
    

      

    package com.factory.factorymethod.pizzasotre;
    
    public class LDCheesePizza extends Pizza {
        @Override
        public void prepare() {
            setName("伦敦的奶酪pizza");
            System.out.println("伦敦奶酪披萨准备");
        }
    }
    

      

    package com.factory.factorymethod.pizzasotre;
    
    public class BJPepperPizza extends Pizza {
        @Override
        public void prepare() {
            setName("北京的胡椒pizza");
            System.out.println("北京胡椒披萨准备");
        }
    }
    

      

    package com.factory.factorymethod.pizzasotre;
    
    
    
    public class BJCheesePizza extends Pizza {
        @Override
        public void prepare() {
            setName("北京的奶酪pizza");
            System.out.println("北京奶酪披萨准备");
        }
    }
    

      

    package com.factory.factorymethod.order;
    
    import com.factory.factorymethod.pizzasotre.BJCheesePizza;
    import com.factory.factorymethod.pizzasotre.BJPepperPizza;
    import com.factory.factorymethod.pizzasotre.Pizza;
    
    public class BJOrderPizza extends OrderPizza {
        @Override
        Pizza createPizza(String orderType) {
            Pizza pizza=null;
            if("cheese".equals(orderType)){
                pizza=new BJCheesePizza();
            }else if("pepper".equals(orderType)){
                pizza=new BJPepperPizza();
            }
            return pizza;
        }
    }
    

      

    package com.factory.factorymethod.order;
    
    import com.factory.factorymethod.pizzasotre.*;
    
    public class LDOrderPizza extends OrderPizza {
        @Override
        Pizza createPizza(String orderType) {
            Pizza pizza=null;
            if("cheese".equals(orderType)){
                pizza=new LDCheesePizza();
            }else if("pepper".equals(orderType)){
                pizza=new LDPepperPizza();
            }
            return pizza;
        }
    }
    

      

    package com.factory.factorymethod.order;
    
    public class PizzaStore {
        public static void main(String[] args) {
            //创建北京口味的各种pizza
            new BJOrderPizza();
            //创建伦敦口味的各种pizza
    //        new LDOrderPizza();
        }
    }
    

      

    运行结果;

    请输入您想订购的披萨种类:
    cheese
    北京奶酪披萨准备
    北京的奶酪pizza baking
    北京的奶酪pizza cutting
    北京的奶酪pizza boxing
    请输入您想订购的披萨种类:
    pepper
    北京胡椒披萨准备
    北京的胡椒pizza baking
    北京的胡椒pizza cutting
    北京的胡椒pizza boxing
    请输入您想订购的披萨种类:
    greek
    订购披萨失败!!!
    

      

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

      

    在这个基础上,我们又新增了地址信息的分类,即有北京口味的pizza 和 伦敦口味的pizza

    package com.factory.absfactory.pizzastore.pizza;
    
    /**
     * 披萨抽象类
     */
    public  abstract class Pizza {
    
        /**
         * 披萨的名字
         */
        protected String name;
    
    
    
        /**
         * 准备原材料,不同的披萨需要准备的原材料是不一样的,这里最好做成抽象方法
         */
        public abstract void prepare();
    
        /**
         * 烘烤
         */
        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 String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    }
    

      

    package com.factory.absfactory.pizzastore.pizza;
    
    public class LDPepperPizza extends Pizza {
    
        @Override
        public void prepare() {
            setName("伦敦的胡椒pizza");
            System.out.println("伦敦胡椒披萨准备");
        }
    }
    

      

    package com.factory.absfactory.pizzastore.pizza;
    
    public class LDCheesePizza extends Pizza {
        @Override
        public void prepare() {
            setName("伦敦的奶酪pizza");
            System.out.println("伦敦奶酪披萨准备");
        }
    }
    

      

    package com.factory.absfactory.pizzastore.pizza;
    
    public class BJPepperPizza extends Pizza {
        @Override
        public void prepare() {
            setName("北京的胡椒pizza");
            System.out.println("北京胡椒披萨准备");
        }
    }
    

      

    package com.factory.absfactory.pizzastore.pizza;
    
    
    public class BJCheesePizza extends Pizza {
        @Override
        public void prepare() {
            setName("北京的奶酪pizza");
            System.out.println("北京奶酪披萨准备");
        }
    }
    

      

    package com.factory.absfactory.pizzastore.order;
    
    import com.factory.absfactory.pizzastore.pizza.Pizza;
    
    /**
     * 一个抽象工厂模式的抽象层
     */
    public interface AbsFactory {
        //让下面的工厂子类来具体实现
        public Pizza createPizza(String orderType);
    }
    

      

    package com.factory.absfactory.pizzastore.order;
    
    import com.factory.absfactory.pizzastore.pizza.BJCheesePizza;
    import com.factory.absfactory.pizzastore.pizza.BJPepperPizza;
    import com.factory.absfactory.pizzastore.pizza.Pizza;
    
    /**
     * 这是工厂类的子类
     */
    public class BJFactory implements AbsFactory {
        @Override
        public Pizza createPizza(String orderType) {
            System.out.println("使用的是抽象工厂模式");
            Pizza pizza=null;
            if("cheese".equals(orderType)){
                pizza=new BJCheesePizza();
            }else if("pepper".equals(orderType)){
                pizza=new BJPepperPizza();
            }
            return pizza;
        }
    }
    

      

    package com.factory.absfactory.pizzastore.order;
    
    import com.factory.absfactory.pizzastore.pizza.*;
    
    /**
     * 这是工厂类的子类
     */
    public class LDFactory implements AbsFactory {
        @Override
        public Pizza createPizza(String orderType) {
            System.out.println("使用的是抽象工厂模式");
            Pizza pizza=null;
            if("cheese".equals(orderType)){
                pizza=new LDCheesePizza();
            }else if("pepper".equals(orderType)){
                pizza=new LDPepperPizza();
            }
            return pizza;
        }
    }
    

      

    package com.factory.absfactory.pizzastore.order;
    
    import com.factory.absfactory.pizzastore.pizza.Pizza;
    
    import java.io.BufferedReader;
    import java.io.IOException;
    import java.io.InputStreamReader;
    
    /**
     * 订购pizza
     */
    public class OrderPizza {
        AbsFactory factory=null;
        public OrderPizza(AbsFactory factory){
            setFactory(factory);
        }
        private void setFactory(AbsFactory factory){
            Pizza pizza=null;
            String orderType="";//用户输入
            this.factory=factory;
            do {
                orderType=getType();
                //factory 可能是北京的工厂子类,也可能是伦敦的工厂子类
                pizza = factory.createPizza(orderType);
                if(null!=pizza){
                    pizza.prepare();
                    pizza.bake();
                    pizza.cut();
                    pizza.box();
                }else {
                    System.out.println("订购失败");
                    break;
                }
    
            }while (true);
        }
        //获取客户希望订购的披萨种类
        private String getType() {
            try {
                BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in));
                System.out.println("请输入您想订购的披萨种类:");
                String str = bufferedReader.readLine();
                return str;
            } catch (IOException e) {
                e.printStackTrace();
                return e.toString();
            }
        }
    }
    

      

    package com.factory.absfactory.pizzastore.order;
    
    public class PizzaStore {
        public static void main(String[] args) {
            new OrderPizza(new BJFactory());
    //当然也可以穿伦敦工厂
        }
    }
    

      

    运行结果:

    请输入您想订购的披萨种类:
    cheese
    使用的是抽象工厂模式
    北京奶酪披萨准备
    北京的奶酪pizza baking
    北京的奶酪pizza cutting
    北京的奶酪pizza boxing
    请输入您想订购的披萨种类:
    pepper
    使用的是抽象工厂模式
    北京胡椒披萨准备
    北京的胡椒pizza baking
    北京的胡椒pizza cutting
    北京的胡椒pizza boxing
    请输入您想订购的披萨种类:
    he
    使用的是抽象工厂模式
    订购失败
    

      

    工厂模式小结;

    1) 工厂模式的意义

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

    2) 三种工厂模式(简单工厂模式、工厂方法模式、抽象工厂模式)

    3) 设计模式的依赖抽象原则

    >创建对象实例时,不要直接new类,而是把这个new类的动作放在一个工厂的方法中,并返回。有的书上说,变量不要指直接持有具体类的引用。

    >不要让类继承具体类,而是继承抽象类或者是实现interface(接口)

    >不要覆盖基类中已经实现的方法。

  • 相关阅读:
    Vue + Element 中的时间自定义选择框的数据传参绑定分析与js格式化时间参数
    vue 给data 数据的重新初始化
    Vue + Element 后台项目与后台的数据对接
    js将两组数据存到你定义的空的对象数组
    Element ui 自定义表格行样式
    vue组件的注册与使用
    Vue + Element 实现下拉选择统计时间数据栏并展示
    Vue + Element后台项目报错(This relative module was not found)
    Echart图的使用技巧,配置相关样式与属性
    7种方法实现数组去重
  • 原文地址:https://www.cnblogs.com/dongyaotou/p/15169635.html
Copyright © 2020-2023  润新知