Factory Method:为何不在工厂类中为每种类型各设一个创建方法?
你提到的这种「给每个产品类型写专属静态创建方法」的实现,确实有两个很直观的好处:IDE自动补全方便,还能给不同类型传不同参数。但它在设计模式的核心目标(扩展性、解耦、可维护性)上存在明显的硬伤,这也是主流场景下不推荐的原因:
1. 直接违反开闭原则
每次新增一个产品类型,你都得修改工厂类的代码——加新的静态方法。而工厂模式的核心诉求之一,就是让产品扩展时尽量不碰原有工厂逻辑。对比两种主流实现:
- 抽象工厂+具体工厂:新增产品只需要加对应的具体工厂类,原有的工厂接口和其他工厂类完全不用改;
- 带参数的
Create(type)方法:新增产品只需要在方法里加个分支判断,工厂类对外的接口不变,调用方的代码也不用改。
但静态方法的方式,不仅要改工厂类,调用方如果要用到新类型,还得调用新的静态方法,相当于把产品扩展的影响扩散到了所有调用点,耦合度拉满。
2. 没法做工厂的多态替换
静态方法属于类本身,不能被继承和重写。如果后续需要替换工厂逻辑——比如测试时用Mock工厂生成假对象,或者在不同环境用不同的工厂实现,静态方法的方式基本没辙。而抽象工厂模式靠抽象层,能轻松切换具体工厂;带参数的工厂类也可以通过继承重写Create方法来适配不同场景。
3. 容易养出「上帝工厂类」
如果产品类型多了,工厂类会被一堆静态方法塞满,变成一个臃肿的「上帝类」,维护起来特别费劲。而且每个静态方法里的初始化逻辑可能有重复(比如日志埋点、通用参数注入),但静态方法很难复用这些逻辑,只能复制粘贴。而带参数的Create可以把通用逻辑抽出来,只在分支里处理差异;抽象工厂则把不同产品的创建逻辑分散到各个具体工厂类,每个类只干一件事,更符合单一职责。
4. 看似灵活,实则破坏了封装
你说「能为不同类型传递不同参数」,但这会让调用方必须清楚每个产品的参数要求,直接违背了工厂模式封装对象创建细节的初衷。调用方本该只关心「我要拿到某个类型的产品」,而不需要知道这个产品创建时需要哪些参数、怎么初始化。
反过来,用抽象工厂或带参数的工厂,你可以在工厂内部把参数逻辑封装好——比如从配置文件读、从依赖容器取,调用方完全不用管这些细节,只用拿结果就行。
例外场景:什么时候可以用这种方式?
当然,这种方式也不是完全不能用:如果你的产品类型非常固定,几乎不会新增,而且调用方确实需要明确控制每个产品的创建参数,那它的便捷性确实能省不少事。但从长期维护和扩展性的角度看,还是更推荐遵循工厂模式的标准实现。
内容的提问来源于stack exchange,提问作者John Doe

