PHP设计模式—工厂模式之抽象工厂模式
定义:
抽象工厂模式:提供一个创建一系列相关或相互依赖对象的接口,而无需指定他们的具体类。抽象工厂模式主要解决涉及到多个产品系列的问题。
代码实例:
先回顾上一篇中工厂方法模式的例子,该示例以 BloggsCal 和 MegaCal 两种格式管理编码。如果增加更多的编码格式,这种类结构会横向增长,但如何为不同类型的 PIM 对象加入编码器,使类结构“纵向”增长呢?
这里将会用到三个相似的类层次结构,分别是预约(Appt)、待办事项(Ttd)以及联系人(Contact)。
1、创建Appt 抽象类
/** * Appt 抽象类 * Class ApptEncoder */ abstract class ApptEncoder { abstract public function encode(); }
2、创建Ttd 抽象类
/** * Ttd 抽象类 * Class TtdEncoder */ abstract class TtdEncoder { abstract public function encode(); }
3、创建Contact 抽象类
/** * Contact 抽象类 * Class ContactEncoder */ abstract class ContactEncoder { abstract public function encode(); }
4、创建BloggsCal Appt 格式处理类
/** * BloggsCal Appt 格式处理类 * Class BloggsApptEncoder */ class BloggsApptEncoder extends ApptEncoder { public function encode() { // TODO: Implement encode() method. return "Appointment data encoded in BloggsCal format\n"; } }
5、创建BloggsCal Ttd 格式处理类
/** * BloggsCal Ttd 格式处理类 * Class BloggsTtdEncoder */ class BloggsTtdEncoder extends TtdEncoder { public function encode() { // TODO: Implement encode() method. return "Ttd data encoded in BloggsCal format\n"; } }
6、创建BloggsCal Contact 格式处理类
/** * BloggsCal Contact 格式处理类 * Class BloggsContactEncoder */ class BloggsContactEncoder extends ContactEncoder { public function encode() { // TODO: Implement encode() method. return "Contact data encoded in BloggsCal format\n"; } }
7、创建MegaCal Appt 格式处理类
/** * MegaCal Appt 格式处理类 * Class MegaApptEncoder */ class MegaApptEncoder extends ApptEncoder { public function encode() { // TODO: Implement encode() method. return "Appointment data encoded in MegaCal format\n"; } }
8、创建MegaCal Ttd 格式处理类
/** * MegaCal Ttd 格式处理类 * Class MegaTtdEncoder */ class MegaTtdEncoder extends TtdEncoder { public function encode() { // TODO: Implement encode() method. return "Ttd data encoded in MegaCal format\n"; } }
9、创建MegaCal Contact 格式处理类
/** * MegaCal Contact 格式处理类 * Class MegaContactEncoder */ class MegaContactEncoder extends ContactEncoder { public function encode() { // TODO: Implement encode() method. return "Contact data encoded in MegaCal format\n"; } }
10、创建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 getTtdEncoder() { // TODO: Implement getTtdEncoder() method. return new BloggsTtdEncoder(); } public function getContractEncoder() { // TODO: Implement getContractEncoder() method. return new BloggsContactEncoder(); } public function getFooterText() { // TODO: Implement getFooterText() method. return "BloggsCal footer\n"; } }
11、创建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 getTtdEncoder() { // TODO: Implement getTtdEncoder() method. return new MegaTtdEncoder(); } public function getContractEncoder() { // TODO: Implement getContractEncoder() method. return new MegaContactEncoder(); } public function getFooterText() { // TODO: Implement getFooterText() method. return "MegaCal footer\n"; } }
12、调用
$mgr = new BloggsCommsManager(); print $mgr->getHeaderText(); print $mgr->getApptEncoder()->encode(); print $mgr->getTtdEncoder()->encode(); print $mgr->getContractEncoder()->encode(); print $mgr->getFooterText(); $mega = new MegaCommsManager(); print $mega->getHeaderText(); print $mega->getApptEncoder()->encode(); print $mega->getTtdEncoder()->encode(); print $mega->getContractEncoder()->encode(); print $mega->getFooterText();
13、结果
BloggsCal header Appointment data encoded in BloggsCal format Ttd data encoded in BloggsCal format Contact data encoded in BloggsCal format BloggsCal footer MegaCal header Appointment data encoded in MegaCal format Ttd data encoded in MegaCal format Contact data encoded in MegaCal format MegaCal footer
总结:
1、解除了系统与实现细节间的耦合。我们可以在示例程序中添加或移除任何数量的编码类型,而不会对系统造成任何影响。
2、我们组合了系统中功能相关的元素。因此,BloggsCommsManager 可以确保只使用与 BloggsCal 格式相关的类。
3、添加新产品会非常痛苦,这是因为我们不仅需要创建新产品的实现类,还需要修改抽象创建者及其所有的实现类来支持这个新产品。