抽象工厂方法模式
在工厂方法模式中,我们通过中间件的方式,形成了以下格式的分离:
使用者
↓
创建者
↓
具体产品
问题
这样,我们无论怎样修正具体产品,都不会影响使用者。现在,我们可以做出来一群小工厂,他们有各自的产品,但形成了模式层面的重复,那么我们如何化解这种重复呢?
在本篇,将通过抽象工厂方法模式——抽象 - 工厂方法 - 模式,来完成对小公司的整合,最初设计(母公司 - 子公司):
接下来,我们要通过抽象类解决多个业务并行的问题。
现在,我们要写一个PIM的数据格式解码器 - Personal Information Manage,会产生预约(Appt)、待办事宜(Ttd)、联系人(Contact)三种数据格式。
我们就可以设计出下列UML:
通过CommsManager
抽象类,我们可以生成具体的所有子公司(子类)。
但事实上,这也一定程度的显示了为什么有些公司做不好某些行业,一旦他哪怕是间接介入子公司,也会影响子公司的血统(这个想法我最早接触于吴军先生的《浪潮之巅》)。
实现
abstract class CommsManager {
abstract function getHeaderText();
abstract function getApptEncoder();
abstract function getTtdEncoder();
abstract function getConteactEncoder();
abstract function getFootText();
}
class BloggsCommsManager extends CommsManager {
function getHeaderText()
{
return "BloggsCal header\n";
}
function getApptEncoder()
{
return new BloggsApptEncoder();
}
function getTtdEncoder()
{
return new BloggsTtdEncoder();
}
function getConteactEncoder()
{
return new BloggsConteactEncoder();
}
function getFootText()
{
return "BloggsCal footer\n";
}
}
在这里,我们用了工厂模式(目录在最后)。设计模式之间经常这样协作,一个模式的创建,可以成为另一个模式的一部分。
这方面的想法就是源于模式本身:他是经过无数次同条件下,实践得出的最优解——未来如果有更好的条件,这个最优解就仍然有优化的空间 / 或者没有存在的。
结果
模式的意义:
彻底的将 业务需求 与 实现细节 分割,现在,我们可以随意的改动编码格式,而不用担心业务层产生BUG;
通过强制整合,所有Blogger格式的内容,都通过Blogger创建者类来实现,不会出错;
当然,添加新产品则是令人苦恼的,为了创建新产品的具体实现,我们必须修改抽象创建者、和他的每一个具体实现。
PHP目前还没有强制规定 方法的返回类型,这产生了一些额外的灵活性。(强制规定返回类型,一般为JAVA之类的 强类型-面向对象-语言)
abstract class CommsManager {
const APPT = 1;
const TTD = 2;
const CONTACT = 3;
abstract function getHeaderText();
abstract function mark( $flag_int );
abstract function getFootText();
}
class BloggsCommsManager extends CommsManager {
function getHeaderText()
{
return "BloggsCal header\n";
}
function mark( $flag_int )
{
switch ($flag_int) {
case self::APPT:
return new BloggsApptEncoder();
case self::TTD:
return new BloggsTtdEncoder();
case self::CONTACT:
return new BloggsConteactEncoder();
}
}
function getFootText()
{
return "BloggsCal footer\n";
}
}
类的接口变得更加紧凑,但也有一定的代价,我们放弃了详细的数据格式方法,而是将其中心化了,客户无法确认是否实现了需要的具体产品。
所以,也要慎用~
当你的项目中,产品越来越多,创建者的数量也随之臃肿,下一篇将介绍抽象工厂方法的变体:原型模式,这种模式可以减少必须创建的类。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。