• Java工厂模式之总有你想不到的知识


    Java工厂模式

    概念

    工厂模式主要是为创建对象提供过渡接口,以便将创建对象的具体过程屏蔽隔离起来,达到提高灵活性的目的。

    工厂模式在一般分为三类:

    1. 简单工厂模式(Simple Factory)
    2. 工厂方法模式(Factory Method)
    3. 抽象工厂模式(Abstract Factory)

    这三种模式从上到下逐步抽象,并且更具一般性

    三种工厂模式

    简单工厂模式

    简单工厂模式又称静态工厂方法模式。从命名上就可以看出这个模式一定很简单。

    它存在的目的很简单:定义一个用于创建对象的接口,先来看看它的组成:

    角色说明
    1)工厂类角色这是本模式的核心,含有一定的商业逻辑和判断逻辑。在java中它往往由一个具体类实现
    2)抽象产品角色它一般是具体产品继承的父类或者实现的接口。在java中由接口或者抽象类来实现。
    3)具体产品角色工厂类所创建的对象就是此角色的实例。在java中由一个具体类实现。

    代码示例

    定义一个抽象产品 Car接口,定义三个具体产品角色类:奔驰、宝马、奥迪实现接口

    package com.shixun.design.factory;
    
    /**
     * 抽象产品 Car接口
     */
    public interface Car {
        void show();
    }
    
    /**
     * 新增的类Aodi
     */
    public class AodiCar implements Car{
        @Override
        public void show() {
            System.out.println("我是Aodi");
        }
    }
    
    /**
     * BenzCar具体产品
     */
    public class BenzCar implements Car {
        @Override
        public void show() {
            System.out.println("我是Benz");
        }
    }
    
    /**
     * BmwCar具体产品
     */
    public class BmwCar implements Car {
        @Override
        public void show() {
            System.out.println("我是Bmw");
        }
    }
    
    • 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

    编写简单工厂用于生产汽车

    package com.shixun.design.factory.simple_factory;
    
    import com.shixun.design.factory.AodiCar;
    import com.shixun.design.factory.BenzCar;
    import com.shixun.design.factory.BmwCar;
    import com.shixun.design.factory.Car;
    
    /**
     * 简单工厂类
     */
    public class SimpleFactory {
        /**
         * 生产汽车(屏蔽生产汽车细节)
         *
         * @param carName 汽车的名称
         * @return
         */
        public static Car produceCar(String carName) {
            //equalsIgnoreCase 忽略大小写 字符串比较相等
            if ("Benz".equalsIgnoreCase(carName)) {
                return new BenzCar();
            } else if ("Bmw".equalsIgnoreCase(carName)) {
                return new BmwCar();
            } else if ("Aodi".equalsIgnoreCase(carName)) {
                return new AodiCar();
            } else {
                throw new RuntimeException("未知类型");
            }
        }
    
        public static void main(String[] args) {
            Car bmw = SimpleFactory.produceCar("bmw");
            bmw.show();
            Car aodi = SimpleFactory.produceCar("aodi");
            aodi.show();
            Car benz = SimpleFactory.produceCar("Benz");
            benz.show();
        }
    }
    
    • 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

    运行结果如下:
    在这里插入图片描述

    使用了简单工厂模式后,我们的程序更加符合现实中的情况;而且客户端免除了直接创建产品对象的责任,而仅仅负责“消费”产品。

    从开闭原则上来分析简单工厂模式
    当工厂生产一新辆车的时候,只要符合抽象产品制定的规定,所以对产品部分来说,它是符合开闭原则的;但是工厂部分好像不太理想,因为每增加一辆新车, 都要在工厂类中增加相应的业务逻辑或者判断逻辑,这显然是违背开闭原则的。可想而知对于新产品的加入,工厂类是很被动的。

    工厂方法模式

    工厂方法模式是简单工厂模式的进一步抽象化和推广,工厂方法模式里不再只由一个工厂类决定那一个产品类应当被实例化,这个决定被交给抽象工厂的子类去做。

    也就是说交给了一个抽象工厂的子类(具体工厂)去实例化产品

    来看下它的组成:

    角色说明
    1)抽象工厂角色工厂方法模式的核心,它与应用程序无关。是具体工厂角色必须实现的接口或者必须继承的父类。 在java中它由抽象类或者接口来实现
    2)具体工厂角色含有和具体业务逻辑有关的代码。由应用程序调用以创建对应的具体产品的对象
    3)抽象产品角色它是具体产品继承的父类或者是实现的接口。在java中一般有抽象类或者接口来实现
    4)具体产品角色具体工厂角色所创建的对象就是此角色的实例。在java中由具体的类来实现

    工厂方法模式使用继承自抽象工厂角色的多个子类来代替简单工厂模式中的“上帝类”。正如上面所 说,这样便分担了对象承受的压力;而且这样使得结构变得灵活 起来:当有新的产品产生时,只要按照 抽象产品角色、抽象工厂角色提供的合同来生成,那么就可以被客户使用,而不必去修改任何已有的代 码。可以看出工厂角色的结构也是符合开闭原则的

    代码示例

    定义一个抽象产品 Car接口,定义三个具体产品角色类:奔驰、宝马、奥迪实现接口

    package com.shixun.design.factory;
    
    /**
     * 抽象产品 Car接口
     */
    public interface Car {
        void show();
    }
    
    /**
     * 新增的类Aodi
     */
    public class AodiCar implements Car{
        @Override
        public void show() {
            System.out.println("我是Aodi");
        }
    }
    
    /**
     * BenzCar具体产品
     */
    public class BenzCar implements Car {
        @Override
        public void show() {
            System.out.println("我是Benz");
        }
    }
    
    /**
     * BmwCar具体产品
     */
    public class BmwCar implements Car {
        @Override
        public void show() {
            System.out.println("我是Bmw");
        }
    }
    
    • 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

    定义一个抽象工厂:

    package com.shixun.design.factory.factory_method;
    
    import com.shixun.design.factory.Car;
    
    /**
     * 工厂(抽象工厂)
     */
    public interface Factory {
        Car produceCar();
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    定义三个具体工厂角色:

    package com.shixun.design.factory.factory_method;
    
    import com.shixun.design.factory.AodiCar;
    import com.shixun.design.factory.Car;
    
    /**
     * Aodi工厂(具体工厂角色)
     */
    public class AodiFactory implements Factory {
        @Override
        public Car produceCar() {
            return new AodiCar();
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    package com.shixun.design.factory.factory_method;
    
    import com.shixun.design.factory.BenzCar;
    import com.shixun.design.factory.Car;
    
    /**
     * Benz工厂(具体工厂角色)
     */
    public class BenzFactory implements Factory {
        @Override
        public Car produceCar() {
            return new BenzCar();
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    package com.shixun.design.factory.factory_method;
    
    import com.shixun.design.factory.BmwCar;
    import com.shixun.design.factory.Car;
    
    /**
     * Bmw工厂(具体工厂角色)
     */
    public class BmwFactory implements Factory {
        @Override
        public Car produceCar() {
            return new BmwCar();
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    定义测试类生产三个产品:

    package com.shixun.design.factory.factory_method;
    
    import com.shixun.design.factory.Car;
    
    /**
     * 使用者
     */
    public class Test {
        public static void main(String[] args) {
            //生产Bmw
            BmwFactory bmwFactory = new BmwFactory();
            Car bmw = bmwFactory.produceCar();
            bmw.show();
    
            //生产Benz
            BenzFactory benzFactory = new BenzFactory();
            Car benz = benzFactory.produceCar();
            benz.show();
    
            //生产Aodi
            AodiFactory aodiFactory = new AodiFactory();
            Car aodi = aodiFactory.produceCar();
            aodi.show();
        }
    }
    
    
    • 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

    运行结果如下:
    在这里插入图片描述

    抽象工厂模式

    内容过多,请参考另一篇博文:https://blog.csdn.net/weixin_45525272/article/details/126317048

    工厂模式优缺点

    优点:

    1、一个调用者想创建一个对象,只要知道其名称就可以了。
    2、扩展性高,如果想增加一个产品,只要扩展一个工厂类就可以
    3、屏蔽产品的具体实现,调用者只关心产品的接口

    缺点:

    每次增加一个产品时,都需要增加一个具体类和对象实现工厂,使得系统中类的个数成倍增加,在一定程度上增加了系统的复杂度,同时也增加了系统具体类的依赖。这并不是什么好事。

  • 相关阅读:
    STM32:DMA数据转运+AD多通道(软件篇)
    接口测试方法论——WebSocket一点通
    头条号如何获得收益、怎样获得收益?
    开发工具——IDE安装 / IDEA子module依赖导入失败编译提示xx找不到符号 / IDEA在Git提交时卡顿
    【开源】基于Vue.js的快递管理系统的设计和实现
    Codeforces Beta Round 5
    java springboot 监控线程池的状态
    以下关于服务器控件的叙述中正确的是
    国际物流报关流程
    URLDNS利用链分析
  • 原文地址:https://blog.csdn.net/weixin_45525272/article/details/126297530