You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于普通父类的Factory Method实现是否合规?代码有无问题?

关于你的Factory Method模式实现的分析与建议

首先直接回应你的两个核心问题:

一、这是不是Factory Method模式?

你的实现不属于标准的Factory Method(工厂方法)模式,它更接近Simple Factory(简单工厂)模式。

为什么这么区分?标准Factory Method的核心是「将对象的创建延迟到子类」:它需要定义一个抽象工厂(接口或抽象类),里面声明一个创建对象的抽象方法,然后由具体的工厂子类去实现这个方法,每个子类对应创建一种产品实例。

而你的MyClassFactory是一个静态类,用一个静态方法集中处理所有产品的创建逻辑——这正是Simple Factory的典型特征:把对象创建的逻辑封装在单一的工厂类里,虽然简化了实现,但没有利用子类扩展创建逻辑的特性。

不过要说明:Simple Factory是Factory Method的简化变体,在业务场景简单、产品子类不会频繁新增的情况下,这种实现完全够用,没必要强行套标准模式,适合自己的需求才是最重要的。

二、代码存在的问题?

你的代码能正常运行,但有几个可以优化的点,避免后续维护踩坑:

  • 父类A的定位模糊:你说部分场景会直接实例化A,但如果A是作为产品的基类,后续还会新增更多子类,直接实例化A可能会导致业务逻辑混乱——比如后续调用子类特有的getX3()方法时,如果拿到的是A的实例,就会报错。如果A不应该被直接实例化,建议改成抽象类;如果确实需要实例化A,要明确它的业务定位(比如作为基础通用实例)。
  • 工厂的判断逻辑违反开闭原则:现在用switch硬编码判断criteria,后续新增子类(比如D、E)时,必须修改MyClassFactory的代码,这不符合「对扩展开放、对修改关闭」的设计原则。
  • 命名不规范:父类A里的x1()是getter,但其他getter都是getXxx格式,这种不一致会导致调用混乱,建议统一成JavaBean标准的getX1();另外getMyClass方法名可以更清晰,比如createInstance;criteria的字符串取值("class B")容易出现拼写错误,建议改成枚举。
  • 异常处理缺失:工厂方法里如果criteria传入错误值,直接返回A的实例,但没有任何提示,后续排查问题会比较麻烦。

三、代码优化示例

1. 统一产品类的命名(可选把A改成抽象类)

// 如果不需要直接实例化A,改成抽象类
public abstract class A { 
    private String x1 = "some value";
    private String x2;

    // 统一getter命名为JavaBean标准格式
    public String getX1() { return x1; }
    public void setX1(String x1) { this.x1 = x1; }
    public String getX2() { return x2; }
    public void setX2(String x2) { this.x2 = x2; }
}

public class B extends A {
    private String x3;
    private String x4;

    public String getX3() { return x3; }
    public void setX3(String x3) { this.x3 = x3; }
    public String getX4() { return x4; }
    public void setX4(String x4) { this.x4 = x4; }
}

public class C extends A {
    private String x5;
    private String x6;

    public String getX5() { return x5; }
    public void setX5(String x5) { this.x5 = x5; }
    public String getX6() { return x6; }
    public void setX6(String x6) { this.x6 = x6; }
}

2. 优化工厂类(符合开闭原则)

用枚举统一产品类型,再用Map存储类型与类的映射,新增子类时只需添加映射,不用修改工厂类的核心逻辑:

// 用枚举定义产品类型,避免字符串硬编码错误
public enum ProductType {
    CLASS_A, CLASS_B, CLASS_C
}

public class MyClassFactory {
    // 存储类型与对应产品类的映射
    private static final Map<ProductType, Class<? extends A>> PRODUCT_MAP = new HashMap<>();

    // 静态块初始化映射
    static {
        PRODUCT_MAP.put(ProductType.CLASS_A, A.class);
        PRODUCT_MAP.put(ProductType.CLASS_B, B.class);
        PRODUCT_MAP.put(ProductType.CLASS_C, C.class);
    }

    public static A createInstance(ProductType type) {
        Class<? extends A> clazz = PRODUCT_MAP.get(type);
        if (clazz == null) {
            // 这里可以抛出自定义异常,或者返回默认实例
            throw new IllegalArgumentException("Invalid product type: " + type);
        }
        try {
            return clazz.getDeclaredConstructor().newInstance();
        } catch (Exception e) {
            // 处理实例化异常,比如抛出自定义异常
            throw new RuntimeException("Failed to create product instance", e);
        }
    }
}

3. 如果要实现标准的Factory Method模式

如果你的业务场景需要频繁新增子类,且希望严格遵循开闭原则,可以改成标准的Factory Method:

// 抽象工厂类
public abstract class AbstractProductFactory {
    public abstract A createProduct();
}

// 具体工厂:创建B实例
public class BProductFactory extends AbstractProductFactory {
    @Override
    public A createProduct() {
        return new B();
    }
}

// 具体工厂:创建C实例
public class CProductFactory extends AbstractProductFactory {
    @Override
    public A createProduct() {
        return new C();
    }
}

// 使用示例
AbstractProductFactory factory = new BProductFactory();
A product = factory.createProduct();

这种方式的好处是新增产品时只需要新增对应的工厂子类,不需要修改现有代码,但会增加类的数量,适合复杂的业务场景。


内容的提问来源于stack exchange,提问作者Genadio

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.14 08:15:51