「设计模式」🌇简单工厂模式(Simple Factory)

955 阅读4分钟

模式动机

假如你手机已经到了更新换代的时候,你正打算去买一部手机,于是你点开网上商店如 JD,想要找到一家同时售卖多种品牌手机的 (集合) 店铺。

假设仅区别手机品牌,不区别该品牌下多种手机类型(如 P30、P40 统称为华为手机,不细分);同时某一手机的操作系统在该店铺具有唯一区分性。

紧接着你找到了一家店铺,它提供了多个不同操作系统的手机如:华为、三星、苹果。这些手机都源自于同一个基类(抽象手机类),只不过在继承基类后不同的子类修改了部分属性从而使得它们可以呈现不同的外观与性能。此时你只需要知道手机的操作系统、名称或者其他参数,提交订单就可以获得参数背后对应的手机。

在这个过程中,用户 (你) 不需要直接创建手机,而是交由工厂 (店家) 去生产/提供指定的产品,用户仅仅“消费”产品。这种模式也就是所谓的简单工厂模式

它避免了如下难以维护的代码在用户端的出现:

定义

简单工厂模式又称静态工厂方法模式,它属于创建型模式

在简单工厂模式中,可以根据参数的不同返回不同类的实例。简单工厂模式专门定义一个类来负责创建其他类的实例,被创建的实例通常都具有共同的父类。

UML 类图

模式结构

简单工厂模式包含如下角色:

  • Factory:工厂类负责实现创建所有实例的内部逻辑
  • Product:抽象产品类是所创建的所有对象的父类,负责描述所有实例所共有的公共接口
  • ConcreteProduct:具体产品类创建的对象充当这个具体类的实例,抽象类的子类实例

更多实例

示例代码

Product.java

public abstract class Product {
    public abstract void use();
}

ConcreteProductA.java

public class ConcreteProductA extends Product {
    @Override
    public void use() {
        // TODO: ConcreteProductA use..
    }
}

ConcreteProductB.java

public class ConcreteProductB extends Product {
    @Override
    public void use() {
        // TODO: ConcreteProductB use..
    }
}

Factory.java

public class Factory {
    // You can implements it by switch-case or if-else too
    private static Map<String, Product> factoryMap = new HashMap<>();

    static {
        factoryMap.put("A", new ConcreteProductA());
        factoryMap.put("B", new ConcreteProductB());
    }

    public static Product createProduct(String type) {
        return factoryMap.get(type.toUpperCase());
    }
}

优缺点

✔工厂类可以使得客户端免除直接创建产品对象的责任,而仅仅“消费”产品;简单工厂模式通过提供专门用于创建对象的工厂类,实现了对职责的划分,同时也实现了对象的创建于对象的使用分离,符合单一职责原则

✔客户端无需知道所创建的具体产品类的类名,只需要提供具体产品类相关联的参数即可,对于一些复杂的类名,通过简单工厂模式可以减少使用者的记忆量。

❌由于工厂类集中了所有产品的创建逻辑(中心化),一旦不能正常工作(单点故障),整个系统都将受到影响。

❌系统扩展困难,一旦添加新产品就不得不修改工厂类的代码逻辑,不符合开闭原则,在产品较多时,有可能造成工厂类难以维护。

❌简单工厂模式由于使用了静态工厂方法,造成工厂角色无法形成基于继承的等级结构。

适用场景

在以下情况推荐使用简单工厂模式:

  • 工厂类负责创建的对象较少:由于创建的对象较少,不会造成方法中的业务逻辑太过复杂。
  • 客户端只知道传入工厂类的参数,对于如何创建对象并不关心:客户端既不需要关心创建细节,甚至连类名都不需要记住,只需要知道类型所对应的参数。

「简单工厂模式」落地

(1)JDK 类库中广泛使用了简单工厂模式,如工具类 java.text.DateFormat,它用于格式化一个本地日期或者时间

(2)Java 加密技术,KeyGenerator.getInstance() 根据不同参数获取不同加密算法的密钥生成器

最后

👆上一篇:「设计模式」理解面向对象的七大设计原则,消除代码中的坏味道

👇下一篇:「设计模式」🏭工厂方法模式(Factory Method)

❤️ 好的代码无需解释,关注「手撕设计模式」专栏,跟我一起学习设计模式,你的代码也能像诗一样优雅!

❤️ / END / 如果本文对你有帮助,点个「赞」支持下吧,你的支持就是我最大的动力!