工厂模式详解

简述

  工厂模式是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

原文地址:https://www.cnblogs.com/qq2210446939/p/13698310.html