工厂模式系列之简单工厂模式

351 阅读3分钟

1. 前言

简单工厂模式是属于创建型模式,又叫做静态工厂方法(Static Factory Method)模式,是工厂方法模式的弱化版,但不属于 23 种 GOF 设计模式之一。简单工厂模式是由一个工厂对象决定创建出哪一种产品类的实例。

2. 实现

假设我们现在自己开了个手机组装厂,需要代工各大品牌的生产组装过程,并且由于我们野心比较大,不只想代工一两个品牌,那么这时候需要先将其中的变化点抽象出来,手机就是一个抽象,为了应对后期的变化,于是先创建出手机的接口(也可以是抽象类),简单起见,这里就只抽象出打电话的功能。

public interface Phone {

    void call();
}

然后创建好我们自己的代工厂

public final class PhoneFactory {

    public static Phone createPhone(String args) {
        
    }
    
    private PhoneFactory() {}
}

现在工厂已经有了,那么就还差具体品牌手机的生产,由于初期资金比较欠缺,这里我们只代理小米和华为,具体品牌手机的实现代码如下:

public class Xiaomi implementes Phone {
    
    @Override
    public void call() {
        System.out.println("Xiaomi - call");
    }
}
public class Huawei implementes Phone {
    
    @Override
    public void call() {
        System.out.println("Huawei - call");
    }
}

这时候手机厂商已经设计好具体手机的功能了,需要找代工厂来量产,我们二话不说接下这两个大单,在 PhoneFactory 中添加工序,代码实现如下:

public final class PhoneFactory {

    public static Phone createPhone(String args) {
        Phone phone = null;
        switch (args) {
            case "Xiaomi":
                phone = new Xiaomi();
                break;
            case "Huawei":
                phone = new Huawei();
                break;
        }
        return phone;
    }
    
    private PhoneFactory() {}
}

现在手机已经可以量产了,于是上市售卖,消费者(即客户端)只需要购买手机就可以直接使用了,不需要知道这个手机是如何生产的,那么代码实现如下:

public class Consumer {
    
    public static void main(String[] args) {
        Phone phone = PhoneFactory.createPhone("Xiaomi");
        phone.call();
    }
}

整个生产过程中,客户端不需要了解手机是如何来的,它只需要通过 PhoneFactory 来获得 Phone ,然后进行使用。现在我们通过代工小米和华为这两个品牌,成功将公司规模扩大了好几倍,于是我们继续代工其他品牌,只需要在 PhoneFactory 中添加新的品牌手机生产工序即可。

3. UML 类图

4. 何时使用简单工厂模式?

在客户端创建对象进行使用时,如果这个对象的实现是不稳定的,因为业务需求需要经常变化,那么简单工厂就派上用场了,由于多态性,客户端始终只需要了解抽象出来的这个类(或者接口),当需求变动时只需要修改工厂类方法的参数来生成另一个具体子类(对于客户端,它完全不知道发生的变化),其他地方不需要改动便可以完全替换功能的实现。

5. 总结

优点:

  • 工厂类中包含了必要的判断逻辑,根据客户端的选择条件动态实例化具体类,对于客户端而言去除了与具体产品的依赖。
  • 由于传入的参数是变量,因此可以引入配置文件,在不修改代码的情况下,通过更改配置文件的变量值来创建不同的具体类。

缺点:

  • 违背了开闭原则,原因是每次增加新类都需要更改工厂类的代码,如果要创建的对象比较多的情况下有一定几率引入 Bug ,不利于后期维护,因此一般只在比较简单的情况下使用。