我有一个自定义框架,其中我有一个使用我自己的Cache
类的类/方法。
目前它紧密耦合。因此,方法实例化Cache
类,如下所示:
public function someMethod ( )
{
$cache = new Cache\HHCache();
}
我想要删除紧耦合,但实际上我已经陷入了困境。
我认为创建某种ServiceProvider
类是个好主意。但我不确定这是否真的是正确的方法。
开始我有HHConfig
文件,该文件具有static
属性,其中定义了缓存类。简而言之:
class HHConfig
{
static $_cacheClass = '\Core\Cache\HHCache';
}
所以基本上我有一个这样的类,它是我框架的 Core 功能的一部分:
interface IHHServiceProvider
{
public function getService ( );
}
然后我有另一个实现此interface
的类。
class HHCacheProvider implements IHHServiceProvider
{
public static function getService ( )
{
$class = HHConfig::$_cacheClass;
return new $class();
}
}
所以现在someMethod
可以使用HHCacheProvider
类来获取Cache
类的实例。
public function someMethod ( )
{
$cache = HHCacheProvider::getService ( );
}
我的IHHServiceProvider
并不像典型的Provider
类,因为您无法真正注册任何Services
。它只是在HHConfig
类中查找要加载的“类”并返回实例。
所以这种方法对我来说感觉不对,但我确实认为它显示了我想要实现的目标。我可以通过哪些方式改善这一点?
请注意我不是在寻找一个简单的依赖注入模式。因为我不想将Cache
类注入每个构造函数类。我需要一种 非紧耦合 方法来从某个方法中以某种方式获取HHCache
类的实例。
可以成为我框架一部分的某种提供者类似乎是正确的方向。
答案 0 :(得分:2)
注意:“提供者”没有任何意义。该名称没有模式。
你应该看一下工厂模式,而不是做一些神奇的“私人”。基本上这个想法如下:
您在将使用某些服务的类中注入工厂(假设Cache
不是您瞄准的唯一服务形式)。
来自工厂的类请求它所需的服务:
if
服务已初始化一次,只是将实例返回到您的else
它创建新实例,存储它并返回“消费者”最简单的代码示例如下:
class ServiceFactory
{
private $storage = [];
public function create( $name )
{
if ( false === array_key_exists( $name, $this->storage ))
{
$instance = new $name;
$this->storage[$name] = $instance;
}
return $this->storage[$name];
}
}
这是一个极其简化的示例,但即使在这种情况下,如果您在任意数量的对象中注入此工厂的实例,它们都可以访问相同的实例池。
如果您决定研究 DI容器的概念,那么工厂也是适合使用它们的地方,而不会将它们降级为服务定位器反模式。
..并且很少有你认为有价值的讲座:
答案 1 :(得分:1)
根据OP请求
特别是因为它将成为框架的一部分,所以应该注入Cache。 DI容器是这里的最佳解决方案,您可以将实际的Cache实现配置为单例。您提出的解决方案与某些服务紧密耦合,难以单独测试。实际上它看起来更像是服务定位器模式而不是提供者。
如果您使用的工厂不会替换DI容器。 DI的要点是代码不应该耦合到外部静态服务。除非你有充分的理由,否则任何对象都应该只使用注入的(通过构造函数或方法参数)依赖。