我总是担心通过字符串引用它们来调用方法。
基本上在我当前的场景中,我使用静态数据映射器方法来创建和返回数据模型对象的数组(例如,SomeDataMapper :: getAll(1234))。模型遵循Active Record设计模式。在某些情况下,可能会返回数百条记录,而且我不想一次将所有内容都放入内存中。所以,我使用迭代器来翻阅记录,如下所示
$Iterator = new DataMapperIterator('SomeDataMapper', 'getAll', array(1234));
while ($Iterator->hasNext()) {
$data = $Iterator->next();
}
这是一个很好的方法吗?以字符串形式传递mapper类的名称和方法是一个坏主意吗?我担心这个想法不能移植到其他语言。对于像Ruby和Python这样的语言,这通常是正确的吗?如果是这样,有人可以推荐一个好的选择吗?
仅供参考,对于未来人们的推荐,我称之为这样的方法:
$method = new ReflectionMethod($className, $methodName);
$returnValue = $method->invokeArgs(null, $parameters);
答案 0 :(得分:3)
这实际上是工厂模式的一个版本 - 使用字符串创建对象实例。
但是,我质疑使用迭代器来控制数据分页的设计思想 - 这不是迭代器的真正目的。除非我们只是名字混淆,但我可能更愿意看到这样的事情。
$pager = new DataMapperPager( 'SomeDataMapper', 'someMethod', array(1234) );
$pager->setPageNum( 1 );
$pager->setPageSize( 10 );
$rows = $pager->getResults();
foreach ( $rows as $row )
{
// whatever
}
当然,DataMapperPager :: getResults()可以返回迭代器或任何你想要的东西。
答案 1 :(得分:1)
这是一种可以接受的方式。 Python和Ruby都支持它,因此应该是可移植的。 Python可以像PHP一样轻松地完成它,但Ruby还有更多功能。至少在Python中,当您引用的特定类尚未在文件中导入或显示时(例如,在您尝试引用它的同一文件中找到该类时),它非常有用。
从Ruby中的字符串中获取类对象:http://infovore.org/archives/2006/08/02/getting-a-class-object-in-ruby-from-a-string-containing-that-classes-name/
答案 2 :(得分:1)
PHP并不真正支持以任何其他方式传递函数。 PHP中的所有动态方法调用函数都采用他们称之为“回调”的函数 - 有关该文档的文档,请参阅http://us.php.net/manual/en/language.pseudo-types.php#language.types.callback。正如您将看到的,它们只是字符串或不同使用模式的字符串数组,所以您离它们不远。
然而,有一些设计模式可以解决这个问题。例如,您可以定义所有映射器类必须实现的DataMapper接口。然后,您可以将映射器实例传递给迭代器,而不是将类和方法作为字符串传递,因为它需要接口,它可以直接调用接口方法。
伪代码:
interface DataMapper
{
public function mapData($data);
}
class DataMapperIterator ...
{
public function __construct(DataMapper $mapper, ...)
{
...
}
...
public function next()
{
... now we can call the method explicitly because of interface ...
$this->mapper->mapData($data);
}
}
class DataMapperImplemenation implements DataMapper
{
...
public function mapData($data)
{
...
}
...
}
使用传入的字符串按名称调用方法并不可怕,可能只有性能损失,因为生成的字节码无法优化 - 总会有符号查找 - 但我怀疑你会注意到这一点得多。