设计模式之工厂方法模式--更加符合开闭原则的工厂模式
工厂方法模式
是简单工厂模式的升级版本,更加符合开闭原则。
定义一个创建对象的接口,让子类决定实例化哪一个类。工厂方法使一个类的实例化延迟到其子类。
为什么要使用工厂方法模式
之前说了 简单工厂模式
,简单工厂模式的工厂类是这样的。
//简单工厂类 class factory{ function static createPay() { if (小程序) { //小程序支付 $pay = new miniWechatPay; } else if (公众号) { //公众号支付 $pay = new jsAPIPay; } else if (pc) { //扫码支付 $pay = new nativePay; } return $pay; } } 复制代码
这样的工厂类是违反了开闭原则的,如果需要增加支付方法就需要修改这个工厂类, 工厂方法模式就是解决这个问题的,使用工厂方法模式后不需要修改工厂类,只需要新增工厂类 。
改成工厂方法模式
为了符合开闭原则,我们需要创建多个工厂类和一个工厂接口。
interface IFactory{ static function createPay(); } class miniFactory implements IFactory{ static function createPay() { return new miniWechatPay; } } class jsAPIFactory implements IFactory{ static function createPay() { return new jsAPIPay; } } class nativeFactory implements IFactory{ static function createPay() { return new nativePay; } } 复制代码
好了,我们把实例化放到了这些子类中,如果增加实例化的需求只需要增加工厂类就可以了。这就是工厂方法模式。
相比简单工厂来说,这有一个缺点就是需要修改的时候虽然不需要修改工厂类了,但是需要修改客户端了。
下面的是原来的客户端。
//微信支付方法 省略了类 function wechatPay() { //...省略 $pay = factory::createPay(); $pay->pay(); } 复制代码
下面的是工厂方法模式的客户端
//微信支付方法 省略了类 function wechatPay() { //...省略 $pay = miniFactory::createPay(); //需要修改这里 $pay->pay(); } 复制代码
如果不想修改客户端也可以再增加一个简单工厂类来实例化工厂方法模式的类。
class factory{ static function createFactory() { if (小程序) { return miniFactory::createPay(); } //省略其他判断和实例化 } } 复制代码
但是我觉得这样还不如直接用简单工厂来的好。
总的来说,简单工厂和工厂方法模式各有优缺点吧,不过对于php来说我觉得简单工厂就足以,虽然有修改代码的风险。但是也还好,而且通过封装成数组来实例化也不需要这一堆if-else。