2011-10-12 75 views
2

可能重复:
Loading multiple versions of the same classPHP的版本类

什么是安装不同版本的PHP类的最佳途径和拨动他们基于配置价值?

这里是我的情况(使用Zend Framework - 不应该的问题,但可能):

我有2个不同的版本,我想能够调用Web服务的。我需要使用我的配置文件中的值在它们之间切换。

现在,我有一个充当工厂的类,并根据配置值确定需要返回哪个类的版本。工厂返回的类的两个版本都扩展了相同的抽象类,所以一旦工厂返回对象,我就可以在其余代码中将这两个版本对待。这似乎没什么问题在理论上,但我最终的代码看起来像这样在我的工厂类,这似乎并没有被很好的做法:

require_once APPLICATION_PATH . '/models/Search/SearchModelV' . $this->config->model->version . '.php'; 

$model_class = 'Search_Model_V' . $this->config->model->version; 
return new $model_class(); 

我使用PHP 5.3,所以我已经实现了命名空间。只要将其用于解决方案即可。

+1

研究使用战略模式。 –

+0

或者也许是工厂模式。 – hakre

+2

请注意,*版本*通常指您的代码演变中的顺序快照。这个问题主要是关于如何使用工厂实现可插拔架构。 – grossvogel

回答

3

我认为解决方案可能是“工厂”模式。这意味着你有一个静态函数可以根据参数创建一个合适的对象。这甚至可以在抽象类上实现,因为您可以在抽象类上声明和调用静态方法。

abstract class Search_Model_Abstract { 
    public static function create($version) { 
     $class = 'Search_Model_V' . $version; 

     return new $class; 
    } 
} 

可以再用Search_Model_Abstract::create($this->config->model->version)

注创建合适的对象,这种方法确实也应该处理可能从构造函数抛出的异常,也应检查$version针对可能的值。

+0

+1您可能想要传递配置本身并让工厂读取它所关心的设置,因此每一个客户端代码都不必知道这个特定设置在配置中的位置。 – grossvogel

+0

@grossvogel是的。 – lonesomeday

2

我认为你的理论是好的,什么让它觉得哈克是你的实现。一些建议。

  1. 使用全局自动加载机制来避免需要遍布整个位置的文件。如果你不这样做,你至少可以在将配置值输入到require_once之前申请(2)。
  2. 在使用之前验证配置设置。我不知道你的案子有什么用,但是最好是白名单,以确保你获得了可接受的价值。
  3. 确保您能够实例化新对象,并在返回之前正确处理错误。
0

理论上你的应用程序不应该关心版本。它只需要使用当前的一个。版本就是这种情况。例如在php中,我们没有file_get_contents,file_get_contents_v51等。我们只使用当前可用的版本。对于将include_path更改为“当前”版本或符号链接或使用“复制”构建脚本等情况,将为您完成这项工作。但那不是你的情况。您需要在同一时间有可用的不同实例。我们不是在谈论版本,而是“策略”。在这种情况下,不能动态构建文件路径。你只有选择在哪里做动态包含。就我们所说的“相同”类同名(我想是这样)而言,我个人会选择使用依赖注入容器,并根据配置值中的“版本”给予容器不同的配置。

例如

$config = array(
'service_v1.0' => array('path' => 'path/to/my/service/v1.0/'); 
'service_v1.1' => array('path' => 'path/to/my/service/v1.1/'); 
); 
$version = 'service_v1.1'; 
DIContainer::create($config[$version]); 

利用上述方案我不关心的依赖(如果有的话)“当前”的服务(例如,不同的服务键,不同的存储等),据我可以描述配置所有这些和注入它们。有关依赖注入的更多详细信息,请参阅here。 我的两毛钱关于问题