• Java工厂模式


    创建一个制作Pizza的例子

    传统方式

    在这里插入图片描述

    1.创建一个Pizza的抽象类 所有其他Pizza继承自Pizza

    public abstract class Pizza {
        String name;
        //准备原材料
        public abstract void prepare();
        //烘培
        public void bake(){
            System.out.println(name+"bake");
        }
        //切块
        public void cut(){
            System.out.println(name+"cut");
        }
        public void setName(String name){
            this.name=name;
        }
    }
    public class GreekPizza extends Pizza {
        @Override
        public void prepare() {
            System.out.println("GreekPizza prepare");
        }
    }
    public class CheesePizza extends Pizza {
        @Override
        public void prepare() {
            System.out.println("CheesePizza prepare");
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28

    2.订购PIzza

    public class OrderPizza {
        public OrderPizza(){
            Pizza pizza=null;
            String orderType; //订购披萨的类型
            Scanner s=new Scanner(System.in);
            //订购披萨
            do{
                System.out.println("输入披萨种类:");
                orderType=s.next();
                if(orderType.equals("greek")){
                    pizza=new GreekPizza();
                    pizza.setName("greek");
                }else if(orderType.equals("cheese")){
                    pizza=new CheesePizza();
                    pizza.setName("cheese");
                }else{
                    break;
                }
                pizza.prepare();
                pizza.bake();
                pizza.cut();
            }while (true);
        }
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25

    此方式的优缺点
    优点:简单易操作
    缺点:违反了OCP原则(对扩展开放,对修改关闭),即当我们给类增加新功能时,尽量不修改代码,或者尽可能少修改代码

    按以上的传统方式,当我们需要新增Pizza时,首先需要新增一个Pizza的子类 然后在OrderPizza中修改代码

    改进思路:把创建Pizza对象封装到类中,这样又新的Pizza种类时,只需要修改该类,其他又创建到Pizza对象的代码就不需要修改了–》简单工厂模式

    简单工厂

    在这里插入图片描述

    简单工厂模式是属于创建型模式 是工厂模式的一种 简单工厂模式是由一个工厂对象决定船舰出哪一种产品的实例
    简单工厂模式:定义一个创建对象的类,由这个类来封装实例化对象的行为
    Pizza类及其子类和上面的传统模式相同:

    订购Pizza:

    public class OrderPizza {
       PizzaSimpleFactory pizzaSimpleFactory;
       Pizza pizza=null;
       public OrderPizza(PizzaSimpleFactory s){
           this.setFactory(s);
       }
       public void setFactory(PizzaSimpleFactory s){
           String orderType="";
           Scanner sc=new Scanner(System.in);
           this.pizzaSimpleFactory=s;
           do{
               System.out.println("输入pizza类型");
               orderType=sc.next();
               pizza=pizzaSimpleFactory.createPizza(orderType);
               if(pizza!=null){
                   pizza.prepare();
                   pizza.bake();
                   pizza.cut();
               }
           }while (true);
    
       }
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24

    Pizza简单工厂:

    public class PizzaSimpleFactory {
        //根据orderType返回对应的Pizza对象
        public Pizza createPizza(String orderType){
            Pizza pizza=null;
            System.out.println("Using SimpleFactory");
            if(orderType.equals("greek")){
                pizza=new GreekPizza();
                pizza.setName("greek");
            }else if(orderType.equals("cheese")){
                pizza=new CheesePizza();
                pizza.setName("cheese");
            }
           return pizza;
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    当后序修改代码时,只需要修改Factory里即可,不再需要修改OrderPizza。因为OrderPizza可能是有多个的,而Factory只有一个,如果修改OrderPizza会很复杂。Factory相当于Pizza和OrderPizza的中间层,来降低Pizza和OrderPizza的耦合

    新需求:点Pizza时可以选择不同口味的Pizza 比如北京的GreekPizza 纽约的GreekPizza
    使用工厂方法模式

    工厂方法模式

    工厂方法模式设计方案:将Pizza项目的实例化功能抽象成抽象方法,在不用的口味点餐子类中具体实现
    工厂方法模式:定义了一个创建对象的抽象方法,由子类决定要实例化的类。工厂方法模式将对象的实例化推迟到子类
    在这里插入图片描述
    此处的OrderPizza就是一个工厂类

    Pizza及其子类:

    public abstract class Pizza {
        String name;
        //准备原材料
        public abstract void prepare();
        //烘培
        public void bake(){
            System.out.println(name+"bake");
        }
        //切块
        public void cut(){
            System.out.println(name+"cut");
        }
        public void setName(String name){
            this.name=name;
        }
    }
    public class BJCheesePizza extends Pizza {
        @Override
        public void prepare() {
            setName("北京奶酪披萨");
            System.out.println("BJCheesePizza prepare");
        }
    }
    public class BJGreekPizza extends Pizza {
        @Override
        public void prepare() {
            setName("北京GreekPiza");
            System.out.println("BJGreekPizza prepare");
        }
    }
    public class LDCheesePizza extends Pizza {
        @Override
        public void prepare() {
            setName("伦敦CheesePiza");
            System.out.println("LDCheesePizza prepare");
        }
    }
    public class LDGreekPizza extends Pizza {
        @Override
        public void prepare() {
            setName("LDGreekPiza");
            System.out.println("LDGreekPizza prepare");
        }
    }
    
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46

    OrderPizza及其子类:

    public abstract class OrderPizza {
    
    
      abstract Pizza createPizza(String orderType);
      public OrderPizza(){
          Pizza pizza=null;
          String orderType;
          Scanner sc=new Scanner(System.in);
          do{
              orderType=sc.next();
              pizza=createPizza(orderType); //抽象方法 由工厂子类完成
              pizza.prepare();
              pizza.bake();
              pizza.cut();
          }while (true);
      }
    }
    public class BJOrderPizza extends OrderPizza {
        @Override
        Pizza createPizza(String orderType) {
            Pizza pizza=null;
            if(orderType.equals("cheese")){
                pizza=new BJCheesePizza();
            }else if(orderType.equals("greek")){
                pizza=new BJGreekPizza();
            }
            return pizza;
        }
    }
    public class LDOrderPizza {
        Pizza pizza=null;
        Pizza createPizza(String orderType){
            if(orderType.equals("greek")){
                pizza= new LDGreekPizza();
            }else if(orderType.equals("cheese")){
                pizza= new LDCheesePizza();
            }
            return pizza;
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41

    PizzaStore:

    //相当于客户端 完成Pizza订购
    public class PizzaStore {
        public static void main(String[] args) {
            BJOrderPizza bjOrderPizza=new BJOrderPizza();
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    抽象工厂模式

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

    在这里插入图片描述
    Pizza及其子类与工厂方法模式相同

    AbsFactory及其子类:

    public interface AbsFactory {
        public Pizza createPizza(String orderType);
    }
    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("greek")){
                pizza=new BJGreekPizza();
            }
            return pizza;
        }
    }
    public class LDFactory implements AbsFactory {
        @Override
        public Pizza createPizza(String orderType) {
           Pizza pizza=null;
            if(orderType.equals("greek")){
               pizza=new LDGreekPizza();
           }else if(orderType.equals("cheese")){
                pizza=new LDCheesePizza();
            }
            return pizza;
        }
    }
    
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29

    OrderPizza:

    public class OrderPizza {
        AbsFactory absFactory;
        public void setFactory(AbsFactory abs){
            this.absFactory=abs;
            Scanner sc=new Scanner(System.in);
            do{
                String orderType = sc.next();
                Pizza pizza = absFactory.createPizza(orderType);
                pizza.prepare();
                pizza.bake();
                pizza.cut();
            }while(true);
        }
        public OrderPizza(AbsFactory abs){
            setFactory(abs);
        }
    
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    工厂模式在JDK中的使用

    Calender中使用了工厂模式

     private static Calendar createCalendar(TimeZone zone,
                                               Locale aLocale)
        {
            CalendarProvider provider =
                LocaleProviderAdapter.getAdapter(CalendarProvider.class, aLocale)
                                     .getCalendarProvider();
            if (provider != null) {
                try {
                    return provider.getInstance(zone, aLocale);
                } catch (IllegalArgumentException iae) {
                    // fall back to the default instantiation
                }
            }
    
            Calendar cal = null;
    
            if (aLocale.hasExtensions()) {
                String caltype = aLocale.getUnicodeLocaleType("ca");
                if (caltype != null) {
                    switch (caltype) {
                    case "buddhist":
                    cal = new BuddhistCalendar(zone, aLocale);
                        break;
                    case "japanese":
                        cal = new JapaneseImperialCalendar(zone, aLocale);
                        break;
                    case "gregory":
                        cal = new GregorianCalendar(zone, aLocale);
                        break;
                    }
                }
            }
            if (cal == null) {
                // If no known calendar type is explicitly specified,
                // perform the traditional way to create a Calendar:
                // create a BuddhistCalendar for th_TH locale,
                // a JapaneseImperialCalendar for ja_JP_JP locale, or
                // a GregorianCalendar for any other locales.
                // NOTE: The language, country and variant strings are interned.
                if (aLocale.getLanguage() == "th" && aLocale.getCountry() == "TH") {
                    cal = new BuddhistCalendar(zone, aLocale);
                } else if (aLocale.getVariant() == "JP" && aLocale.getLanguage() == "ja"
                           && aLocale.getCountry() == "JP") {
                    cal = new JapaneseImperialCalendar(zone, aLocale);
                } else {
                    cal = new GregorianCalendar(zone, aLocale);
                }
            }
            return cal;
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50

    Calender的创建是通过Calender.getInstance()来获得实例对象
    getInstance就是调用上面的createCalendar方法

        public static Calendar getInstance()
        {
            return createCalendar(TimeZone.getDefault(), Locale.getDefault(Locale.Category.FORMAT));
        }
    
    • 1
    • 2
    • 3
    • 4

    如上的createCalendar()中
    通过一个switch来判断时区从而创建不同的对象,是一种简单工厂模式

    小结

    工厂模式的意义:
    将实例化对象的代码提取出来,放到一个类中统一管理和维护,达到和主项目的依赖关系的解耦,从而提高项目的扩展和维护性。
    设计模式的依赖抽象原则:
    创建对象实例时,不要直接new类,而是把这个new类的动作放在一个工厂的方法中,并返回
    不要让类继承具体类,而是继承抽象类或者实现interface
    不要覆盖基类中已经实现的方法

  • 相关阅读:
    (UE4升级UE5)Selected Level Actor节点升级到UE5
    Web 性能优化:TCP
    一看就会的Chromedriver(谷歌浏览器驱动)安装教程
    Python redis 使用教程
    “面向大厂编程”一线互联网公司面试究竟问什么?打入内部针对性学习!
    计算机毕业设计Java物流信息管理系统(源码+系统+mysql数据库+Lw文档)
    无人驾驶相关硬件汇总
    BIM算量与传统算量软件的对比和模型精准解决方案
    满足你甜食需求的葡萄酒是怎样的?
    可编程数据平面(论文阅读)
  • 原文地址:https://blog.csdn.net/qq_56892136/article/details/126068836