PHP设计模式—工厂模式之工厂方法模式
定义:
工厂方法模式:定义一个用于创建对象的接口,让子类决定实例化哪一个类。工厂方法使一个类的实例化延迟到其子类。
代码实例:
这里还是接着上篇简单工厂模式的那个例子,改成工厂方法模式。
1、创建一个抽象类 ApptEncoder
/** * 抽象类 * Class ApptEncoder */ abstract class ApptEncoder { abstract public function encode(); }
2、创建 BloggsCal 格式处理类
/** * BloggsCal 格式处理类 * Class BloggsApptEncoder */ class BloggsApptEncoder extends ApptEncoder { public function encode() { // TODO: Implement encode() method. return "Appointment data encoded in BloggsCal format\n"; } }
3、创建 MegaCal 格式处理类
/** * MegaCal 格式处理类 * Class MegaApptEncoder */ class MegaApptEncoder extends ApptEncoder { public function encode() { // TODO: Implement encode() method. return "Appointment data encoded in MegaCal format\n"; } }
4、创建工厂抽象类 CommsManager
/** * 工厂抽象类 * Class CommsManager */ abstract class CommsManager { abstract public function getHeaderText(); abstract public function getApptEncoder(); abstract public function getFooterText(); }
5、创建 BloggsCal 工厂类
/** * BloggsCal 工厂类 * Class BloggsCommsManager */ class BloggsCommsManager extends CommsManager { public function getHeaderText() { // TODO: Implement getHeaderText() method. return "BloggsCal header\n"; } public function getApptEncoder() { // TODO: Implement getApptEncoder() method. return new BloggsApptEncoder(); } public function getFooterText() { // TODO: Implement getFooterText() method. return "BloggsCal footer\n"; } }
6、创建 MegaCal 工厂类
/** * MegaCal 工厂类 * Class MegaCommsManager */ class MegaCommsManager extends CommsManager { public function getHeaderText() { // TODO: Implement getHeaderText() method. return "MegaCal header\n"; } public function getApptEncoder() { // TODO: Implement getApptEncoder() method. return new MegaApptEncoder(); } public function getFooterText() { // TODO: Implement getFooterText() method. return "MegaCal footer\n"; } }
7、调用:
// 如果要换成 MegaCal 格式处理,直接换成 $mar = new MegaCommsManager() 就可以了 $mgr = new BloggsCommsManager(); print $mgr->getHeaderText(); print $mgr->getApptEncoder()->encode(); print $mgr->getFooterText();
8、结果:
BloggsCal header Appointment data encoded in BloggsCal format BloggsCal footer
总结:
1、使用工厂方法模式,如果需要新增一种格式处理,就不需要修改原有的工厂类了,只需要为这些抽象类实现新的子类即可。这样整个工厂和产品体系其实都没有修改的变化,而只是扩展的变化,这就符合了“开放-封闭原则”。
2、工厂方法模式实现时,客户端需要决定实例化哪一个工厂来实现,选择判断的问题还是存在的,也就是说,工厂方法把简单工厂的内部逻辑判断移到了客户端代码来进行。你想要加功能,本来修改工厂类,而现在是修改客户端。
3、工厂方法模式的缺点是由于每加一个产品,就需要加一个产品工厂的类,增加了额外的开发量。