zoukankan      html  css  js  c++  java
  • 工厂模式详解

    简述

      工厂模式是Java最常用的设计模式之一,这种模式属于创建型模式,提供了一种创建对象的最佳模式。它并不是一个独立的设计模式,而是三种功能接近的设计模式的统称,分别是简单工厂模式工厂方法模式抽象工厂模式

    案例引入

      当我们实例化一个对象的时候,一般我们直接使用new关键字,但我们有没有想到如果创建对象需要一系列复杂的初始化过程,我们就要在对象的构造函数写很长很长的代码,大大降低了程序的可读性,同时也可能导致程序的耦合度较高,这里就可以提到我们的工厂模式了。

    简单工厂模式

      我们在实例化对象的时候,不使用new关键字,而是交由一个新的类,叫工厂类创建。

      我们来看一个例子,在我们的业务代码中,有个被广泛引用的“口罩”类,这里类实例需要在许多地方被创建和初始化,且初始化的代码较为复杂。

    public class Mask {
        //构造函数
        public Mask(){
            // .....
            // 100行初始化代码
        }
    }

      此时我们就可以新建一个口罩工厂类,用于实例化口罩类,把初始化代码搬进工厂里面。

    public class MaskFactory {
     
        public Mask createMask() {
            Mask mask new Mask();
            // .....
            // 100行初始化代码
            return mask;
        }
    }

      如果口罩类存在子类,可以是继承,可以是接口

      我们就根据输入的参数来决定生产出哪种产品

       像这样通过工厂类创建对象,且根据传入的参数决定具体子类对象的做法,就是简单工厂模式。

    工厂方法模式

      但若我们需要新加新的口罩子类,口罩工厂的创建方法中就需要新增新的if-else判断,这样就不符合面向对象的开放-封闭原则。

      所谓面向对象的开放-封闭原则,就是在程序中对“扩展”开放,对“修改”封闭。如果每次业务改动都要增加新的if-else,就涉及对旧有代码的修改,不但容易出错,可读性也不好。

      想要解决这个问题,我们可以为每个口罩子类创建对应的工厂子类,这些工厂子类分别实现抽象的工厂接口。这样一来,我们只需实例化不同的工厂子类,调用创建方法,得到的就是对应的口罩对象,这背后是面向对象的多态特性。

      根据这个思路,我们重构一下工厂,现在工厂是个接口,抽象方法是createMask。

      然后工厂有两个子类——高端口罩工厂和低端口罩工厂

      他们实现了createMask方法

       在代码中,工厂类变成了抽象的接口,高端口罩工厂和低端口罩工厂这两个子类分别实现了这两个接口。

      在客户端,想要创建什么口罩对象,只需要实例化不同的工厂子类,然后调用他们的创建方法即可,无需再传入参数。

       像这样每一个口罩子类都对应一个工厂子类,利用多态性质动态创建对象的模式,就是工厂方法模式。

    抽象工厂模式

      如果业务中我们要创建口罩,防毒面具,防护服三种产品,且每一种产品都包含高端到低端两类,如果按照工厂方法模式创建工厂子类,就如下图所示:

      当产品数量很多的时候,工厂类的数量也会越来越多,搞得非常复杂。

      那该怎么办呢——我们不需要为每一个产品配置一个工厂,而是可以把这些产品进行分组。对于上面的例子我们可以分成高端组和低端组,由同一个工厂类的不同方法创建。

      我们以口罩和防护服举例,他们是两个接口,分别由高端和低端两个实现类:

    public interface IMask {
        void showMask();
    }
     
    public class LowEndMask implements IMask {
        @Override
        public void showMask(){
            System.out.println("我的低端口罩");
        }
    }
     
    public class HighEndMask implements IMask {
        @Override
        public void showMask() {
            System.out.println("我是高端口罩");
        }
    }
     
    public interface IProtectiveSuit {
        void showSuit();
    }
     
    public class LowEndProtectiveSuit implements IProtectiveSuit {
        @Override
        public void showSuit() {
            System.out.println("我是低端防护服");
        }
    }
     
    public class HighEndProtectiveSuit implements IProtectiveSuit {
        @Override
        public void showSuit() {
            System.out.println("我是高端防护服");
        }
    }

      然后是工厂类,因为产品分成了高端和低端两个组,工厂也就分成了高端工厂和低端工厂,各自负责组内产品的创建:

    public interface IFactory {
        //创建口罩
        IMask createMask();
        //创建防护服
        IProtectiveSuit createSuit();
    }
     
    public class LowEndFactory implements IFactory {
        @Override
        public IMask createMask() {
            IMask mask =  new LowEndMask();
            // .....
            //  LowEndMask的100行初始化代码
            return mask;
        }
     
        @Override
        public IProtectiveSuit createSuit() {
            IProtectiveSuit suit =  new LowEndProtectiveSuit();
            // .....
            //  LowEndProtectiveSuit的100行初始化代码
            return suit;
        }
    }
     
    public class HighEndFactory implements IFactory {
        @Override
        public IMask createMask() {
            IMask mask =  new HighEndMask();
            // .....
            // HighEndMask的100行初始化代码
            return mask;
        }
     
        @Override
        public IProtectiveSuit createSuit() {
            IProtectiveSuit suit =  new HighEndProtectiveSuit();
            // .....
            //  HighEndProtectiveSuit的100行初始化代码
            return suit;
        }
    }

      然后我们写test类,通过实例化不同工厂子类,调用不同创建方法,就可以创建出不同的产品:

      像这样把产品分组,组内不同的产品对应同一工厂的不同方法的设计模式,就叫做抽象工厂模式。

    总结

      •简单工厂模式有唯一的工厂类,工厂类的创建方法根据传入的参数做if-else条件判断,决定最终创建什么样的产品对象。

      •工厂方法模式由多个工厂类实现工厂接口,利用多态来创建不同的产品对象,从而避免了冗长的if-else条件判断。

      •抽象工厂模式把产品子类进行分组,同组中的不同产品由同一个工厂子类的不同方法负责创建,从而减少了工厂子类的数量。

    reference

      程序员小灰:https://blog.csdn.net/bjweimengshu/article/details/108591085

            https://blog.csdn.net/bjweimengshu/article/details/108459337

  • 相关阅读:
    vue3 中的路由传参
    js还原底层简单的history路由
    js还原底层简单的hash路由
    使用proxy以及Reflect还原vue3中的shallowReadonly 与 readonly响应式的原理
    flex布局兼容浏览器处理
    使用proxy以及Reflect还原vue3中的shallowReactive与reactive响应式的原理
    TS学习笔记--其他(声明文件、内置对象)
    TS学习笔记--泛型
    TS学习笔记--函数
    springboot+mybatis-plus快速精简配置
  • 原文地址:https://www.cnblogs.com/qq2210446939/p/13698310.html
Copyright © 2011-2022 走看看