在PHP(<;5.3)中创建动态工厂方法
通常如何在PHP中创建动态工厂方法?所谓动态工厂方法,我指的是一种工厂方法,它将根据给定参数的某些方面自动发现要创建的对象。最好也不要先在工厂登记。不过,我同意将可能的对象放在一个公共位置(目录) 我希望避免在factory方法中使用典型的switch语句,例如:在PHP(<;5.3)中创建动态工厂方法,php,dynamic,factory,Php,Dynamic,Factory,通常如何在PHP中创建动态工厂方法?所谓动态工厂方法,我指的是一种工厂方法,它将根据给定参数的某些方面自动发现要创建的对象。最好也不要先在工厂登记。不过,我同意将可能的对象放在一个公共位置(目录) 我希望避免在factory方法中使用典型的switch语句,例如: public static function factory( $someObject ) { $className = get_class( $someObject ); switch( $className )
public static function factory( $someObject )
{
$className = get_class( $someObject );
switch( $className )
{
case 'Foo':
return new FooRelatedObject();
break;
case 'Bar':
return new BarRelatedObject();
break;
// etc...
}
}
我的具体案例涉及工厂根据要投票的项目创建投票存储库。这些项目都实现了一个Voteable
接口。大概是这样的:
Default_User implements Voteable ...
Default_Comment implements Voteable ...
Default_Event implements Voteable ...
Default_VoteRepositoryFactory
{
public static function factory( Voteable $item )
{
// autodiscover what type of repository this item needs
// for instance, Default_User needs a Default_VoteRepository_User
// etc...
return new Default_VoteRepository_OfSomeType();
}
}
我希望能够在不涉及工厂实现的情况下,为这些项目插入新的可投票项目和投票存储库。如果switch语句不存在,则基本上只能使用命名约定。获取传入对象的类并使用它实例化新类。下面是一个简单的例子
//pseudo code, untested
class Default_VoteRepositoryFactory
{
public static function factory( Voteable $item, $arg1, $arg2 )
{
$parts = explode('_', get_class($item));
$type = array_pop();
$class = 'Default_VoteRepository_' . $type;
return new $class($arg1, $arg2);
// autodiscover what type of repository this item needs
// for instance, Default_User needs a Default_VoteRepository_User
// etc...
}
//can be as complex or as simple as you need
protected static function getType(stdClass $item)
{
$parts = explode('_', get_class($item));
return array_pop($parts);
}
}
你能进一步解释为什么投票库需要知道它给出了什么样的
Votable
实现吗?@strager:是的,投票库最初将基于每个Votable项的一个db表。这是为了在我觉得需要将某个特定项目的投票权转移到其他地方时,使它们保持轻量级,并可用于其他类型的存储库。@strager:不过你给了我一些思考的东西。我突然意识到,如果我想用另一份回购协议替换某一特定项目的一份回购协议,我可能还需要联系工厂但是,由于这是一个特定的情况,我仍然想知道一种在其他情况下实现这一点的好方法。投票库本身中不能有Votable
子类数据库表名的映射吗?存储库有一个数据表名,可以用某个子类来标识它,factory方法使用映射创建一个子类。@strager:这也是可能的。我想我得再仔细考虑一下。谢谢你的建议。我很感激。