特点:
- 会产生不必要的子类化
- 结构层次与产品类的层次结构相同
使用场景:
大型项目,需要生成大量对象时,
**工厂模式+抽象工厂模式+原型模式+服务定位器**组合使用。

问题:
假设一个支付系统中,客户要求当前系统要使用微信支付,其中一个是 **WechatAppPly** 对象,但客户强调之后可能会扩展支付业务,要支持:支付宝、银联等支付 。
针对目前已知情况,可以创建以下两个抽象类:
CommonsManagerAppPly
AppPly 负责管理产品,而 CommonsManager 负责创建具体的支付产品。
如果我要得到具体的 AppPly 呢?我可以把生成 AppPly具体子类的推给客户端(调用方)来解决,但只是推迟了问题的发生,现在我想要彻底解决这个问题,接下来我直接在 CommonsManager 类中直接实例化一个WechatAppPly
abstract AppPly{public function ply(): void;}// 具体产品class WechatAppPly extends AppPly{public function ply(): void{// 微信支付逻辑}}
abstract CommonsManager{public static function getAppPly(): AppPly{return new WechatAppPly();}}
CommonsManager负责生成 WechatAppPly类,但是现在,客户要求新增支付宝支付功能,我简单的添加一个条件语句到 CommonsManager::getAppPly()方法中即可。接下来我修改 CommonsManager类,他它可以同时处理 WchatAppPly 和 ALiAppPly
class ALiAppPly extends AppPly{public function ply(): void{// 支付宝支付逻辑}}
abstract CommonsManager{public const WECHAT = 'wechat';public const ALi = 'ali';private ?string $mode;public function __construct(string $mode){$this->mode = $mode;}public function getAppPly(): AppPly{return match($this->model){'wechat' => return new WechatAppPly();default => new ALiAppPly();}}}// 调用过程$com = new CommonsManager(CommonsManager::WECHAT);// 执行支付方法$com->getAppPly()->ply(); // wechat ply$com = new CommonsManager(CommonsManager::ALi);$com->getAppPly()->ply();// ali ply
这种方式仍然存在一个小问题。条件语句有时候被称为 “代码异味”,如果这时候,如果这时候,客户要求在支付前和支付后要记录当前支付功能的日志。那意味着同样的我要在 CommonsManager 类中提供与生成支付类相同的条件判断语句来创建对应的记录器
abstract CommonsManager{public const WECHAT = 'wechat';public const ALi = 'ali';private ?string $mode;public function __construct(string $mode){$this->mode = $mode;}public function getAppPly(): AppPly{return match($this->model){'wechat' => return new WechatAppPly();default => new ALiAppPly();}}public function recordBeforePayLog(){if ($this->model === 'wechat') {// 记录微信支付开始前记录}else {// 记录支付支付开始前记录}}
现在问题已经很暴露得很明显了,特别是还需要再添加一个 recordAfterPayLog() 方法时,这种检查会越来越多。这些条件语句可以被多态所替代。可以为每种支付编写一个 CommonsManager 的子类,让它们各自实现 getAppPly() 方法。

以下是简化的示例代码:
abstract AppPly{abstract public function ply(): void;}// 具体产品实现class WechatAppPly extends AppPly{public function ply(): void{// 微信支付逻辑}}
abstract CommonsManager{abstract public function getAppPly(): AppPly;abstract public function recordBeforePlyLog(): void;abstract public function recordAfterPlyLog(): void;}// 产品创建者class WechatAppPlyCommonManager extends CommonsManager{public function getAppPly(): AppPly{return new WechatAppPly();}public function recordBeforePlyLog(){// 记录支付前日志}public function recordAfterPlyLog(){// 记录支付后日志}}// 调用$mgr = new WechatAppPlyCommonManager();$mgr->recordBeforePlyLog();$mgr->getAppPly()->ply();$mgr->recordAfterPlyLog();
即使现在要求实现 AliAppPly 时,只需要为抽象类型实现新的子类即可,修改后包含 AliAppPly 类类图如下所示:
总结:
工场模式使用起来还是有缺陷的,前面讲过,虽然它规避了重复的条件语句,分离了创建者与产品类之间的耦合,但是它衍生出了另一个问题,它的层次结构变得和产品类的层次结构相同。形成了另一种特殊的代码重复,并且产生了不必要的子类。
