单例、工厂、策略模式需在具体问题中辨认试错:单例用于资源密集/需状态同步对象(如dbconn、logger),工厂解耦创建逻辑(简单工厂适合小项目,工厂方法支持多环境),策略实现运行时算法替换(接口+多实现,无状态),三者嵌套使用时须明确边界——工厂管“造谁”,策略管“怎么算”,单例管“谁来共享”。

单例、工厂、策略这三种模式不是“学完就能用”,而是得在具体问题里反复辨认、试错、替换——比如你刚写完一个 new DbConn(),下一秒就该想:这里要不要改成单例?
为什么 new 一个对象后,马上要怀疑是不是该用单例?
单例本质是「强制复用同一实例」,不是为炫技。它真正起作用的场景很窄,但一旦踩中,效果立竿见影:
- 数据库连接(
DbConn)、日志写入器(Logger)、配置管理器(Config)这类资源密集或需状态同步的对象,重复new会导致连接数爆表、日志错乱、配置不一致 -
getInstance()必须是静态方法,且构造函数和__clone()必须私有——漏掉任一,单例就失效,你可能还在用两个不同实例却浑然不觉 - PHP-FPM 模式下,单例只在当前请求生命周期内唯一;不要指望它跨请求共享数据(那是缓存/Redis 的事)
工厂模式不是“把 new 包一层”,而是为解耦创建逻辑
当你发现代码里散落着十几处 new HaierTv()、new LenovoPc(),而且这些类名/参数/依赖随时会变,工厂才真正必要:
- 简单工厂(如
ProductFactory::createTV())适合小项目,但违反开闭原则——加个新 TV 品牌就得改工厂类 - 工厂方法(抽象类
Factory+ 子类ChinaFactory/USFactory)更适合多环境,比如测试时返回 mock 对象,生产时返回真实服务 - 别在工厂里做业务判断(比如根据用户等级返回不同对象),那是策略模式的活儿——混用会让工厂越来越重、越来越难测
策略模式的核心是「运行时换算法」,不是写一堆 if-else
你写过类似这样的代码吗?
if ($userType === 'vip') {
$discount = $price * 0.8;
} elseif ($userType === 'student') {
$discount = $price * 0.9;
} else {
$discount = $price;
}
这就是策略模式要替掉的东西。正确做法:
- 定义统一接口(如
interface DiscountStrategy),声明calculate($price) - 每个策略实现该接口(
VipDiscount、StudentDiscount) - 客户端只依赖接口,不关心具体类——换折扣规则只需换传入的策略对象,不用动主流程
- 注意:策略对象本身不该持有状态(比如不能在
VipDiscount里存用户 ID),否则容易引发并发问题
最常被忽略的一点:这三种模式不是孤立的。一个支付模块里,你可能用工厂创建支付网关,用策略选扣款逻辑,再用单例管理全局支付配置——它们嵌套使用时,边界必须划清:工厂管“造谁”,策略管“怎么算”,单例管“谁来共享”。混淆职责,比不用模式还危险。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











