工厂模式疑问:为何用工厂替代直接new?附代码求鉴
聊聊你的工厂模式疑问与代码实现
嘿,你的问题真的戳中了很多刚接触设计模式同学的痛点——“好好的new不用,为啥非要整个中间层?这不是多此一举吗?”先给你把这个逻辑理明白,再看你的代码~
先搞懂:工厂模式到底解决啥问题?
你说的“冗余中间类”其实是解耦的必要代价,工厂模式核心是把「对象创建逻辑」和「对象业务逻辑」分开,好处主要有这几点:
- 不用到处改代码:以后新增一款
SUVCar,你只需要在工厂里加个分支,所有调用的地方不用动;如果直接new,每个用到new SUVCar的地方都得改,维护起来头大。 - 隐藏复杂细节:如果某个车型实例化需要一堆参数(比如
new AutoCar('v6', 'red', 2024)),这些逻辑都可以塞在工厂里,调用方只需要传个type就行,不用关心底层怎么创建。 - 统一管理对象:比如你想给所有新车加个初始化日志,或者缓存已经创建过的对象,直接在工厂里加逻辑就行,不用逐个修改具体类。
你的代码是不是工厂模式?写法对吗?
你的代码属于简单工厂模式(也叫静态工厂模式),是工厂模式家族里最基础的一种,写法是完全正确的!不过有几个可以优化的小细节,让它更健壮:
现有代码的优点
你把工厂方法放在抽象父类里,调用方只需要通过CarAbstract::factory('xxx')就能拿到实例,不用直接依赖AutoCar、TruckCar这些具体类,已经实现了“创建与使用分离”的核心目标。
可以优化的地方
- 违反开闭原则:每次加新车型都要修改
CarAbstract的factory方法,虽然简单但不够灵活。如果想更贴合设计原则,可以把工厂抽成独立的类(比如CarFactory),这样新增车型时只加新类,不用改工厂逻辑(不过简单场景下,现有写法完全够用,不用过度设计)。 - 异常处理缺失:如果传了一个不存在的
type(比如'motorcycle'),现在会返回null,后续调用makeSignal会报错。最好加个default分支,抛出明确的异常。 - 静态方法的局限性:静态方法不能被继承重写,如果以后需要不同的工厂逻辑(比如不同地区的车型配置不同),静态工厂就不太好扩展,这时候可以考虑用实例工厂。
优化后的示例代码
abstract class CarAbstract { abstract public function makeSignal(); } class AutoCar extends CarAbstract { public function makeSignal() { return 'beep-beep'; } } class TruckCar extends CarAbstract { public function makeSignal() { return 'faa-faa'; } } // 独立的工厂类,把创建逻辑和抽象类解耦 class CarFactory { public static function create($type) { return match($type) { 'automobile' => new AutoCar(), 'truck' => new TruckCar(), default => throw new InvalidArgumentException("Unknown car type: {$type}"), }; } } // 调用示例 try { $auto = CarFactory::create('automobile'); $truck = CarFactory::create('truck'); echo $auto->makeSignal() . PHP_EOL; // 输出 beep-beep echo $truck->makeSignal() . PHP_EOL; // 输出 faa-faa } catch (InvalidArgumentException $e) { echo 'Error: ' . $e->getMessage(); }
最后再唠一句
不用纠结“是不是必须用工厂模式”,如果你的业务很简单,直接new完全没问题。但当你发现需要频繁新增对象、或者对象创建逻辑变复杂时,工厂模式的价值就体现出来了——它不是为了“炫技”,而是为了让代码更好维护。
内容的提问来源于stack exchange,提问作者Alex Filatov
相关产品推荐
相关产品推荐

