包装器 类 和依赖注入
wrapper classes and dependency injection
众所周知,wrapper classes 的意义在于封装了另一个class 或组件的功能。这是一个简单的 Class,它包装了 PHP Predis 库的一小部分:
class CacheWrapper {
private $client;
public function __construct(){
$this->client = new Predis\Client();
}
public function set($key, $value){
$this->client->set($key, $value);
}
public function get($key){
return $this->client->get($key);
}
}
这里是使用这个包装器的简单代码 class :
$client = new CacheWrapper();
echo $client->get('key1');
这个 class 可以完美工作的问题是它在 class 内部创建了依赖项,我想通过将依赖项注入 class 而不是让 class 来创建它的依赖项,因此包装器 class 将如下所示:
class CacheWrapper {
private $client;
public function __construct(Predis\Client $predisObj){
$this->client = $predisObj;
}
public function set($key, $value){
$this->client->set($key, $value);
}
public function get($key){
return $this->client->get($key);
}
}
所以我必须编写以下代码来使用包装器 class :
$predis = new Predis\Client();
$client = new CacheWrapper($predis);
echo $client->get('key1');
但我认为没有必要使用包装器 class,因为我仍然在我的代码中使用原始的 class。所以我的问题是:依赖注入和包装器 class 概念是否相互矛盾并且不能一起使用,解决此类问题的最佳方法是什么?
当您确切知道要扩展的对象时,最好使用普通继承。
依赖注入适用于当您知道自己将 extending/using class 满足某些基本条件但可能超出此条件或由其他开发人员定义的情况。在那种情况下,您将代码设置为需要一个基础 class(或接口),并让您的 class 的用户确切地决定要扩展哪个实现。
tl;dr
如果您的 class 将始终用作:
$predis = new Predis\Client();
$client = new CacheWrapper($predis);
echo $client->get('key1');
然后依赖注入没有添加任何有用的东西。但是,如果它可能是:
$other = new OtherPredisLikeClass\Client();
$client = new CacheWrapper($other);
echo $client->get('key1');
然后依赖注入让你的 class 的用户无需重写你的 class.
就可以使用它
As everybody knows, the point of wrapper classes is encapsulates the
functionality of another class or component
这实际上并不准确。 "Wrapper Classes" 并不像你暗示的那么简单。有许多设计模式 "wrap" a class。
适配器模式 'wraps' 当所需的 API 与您拥有的 class 的 API 不匹配时的对象。
Facade 模式为更大的代码体提供了一个简化的接口。
Class A{
String setValueFirstHalf(String)
String setValueSecondHalf(String)
Void getValue()
}
// Pseudo-code for 'wrapper' that is an 'adapter pattern' impl.
// This class 'wraps' A and changes the API
Class WrapsA_Adapter{
String setFirst(String) {myA.setValueFirstHalf(String)}
String setSecond(String) {myA.setValueSecondHalf(String)}
Void get() {myA.getValue()}
}
// Pseudo-code for 'wrapper' that is an 'facade pattern' impl.
// This class 'wraps' A and changes the API to 'simplify' it.
// Often the 'facade pattern' uses several classes to do its task,
// but it 'can' use just one like we did below. (this example is obviously a stretch)
Class WrapsA_Facade{
String get()
Void set(String first, String second){
myA.setValueFirstHalf (first);
myA.setValueSecondHalf(second);
}
}
参见:Adapter pattern, Facade pattern
现在直接回答你的问题:
does dependency injection and wrapper class concepts goes against each
other and can't be used together and what is the best way to solve
issue like this ?
他们并不是天生对立的。
您可以很容易地拥有一个 WrapperFacade 实现,其中 Facade 注入了接口的 'specific' 实例。
如果适配器正在适配接口,并且您正在注入该接口的特定实现以供其使用,则具有依赖项注入的适配器模式也将有效。
众所周知,wrapper classes 的意义在于封装了另一个class 或组件的功能。这是一个简单的 Class,它包装了 PHP Predis 库的一小部分:
class CacheWrapper {
private $client;
public function __construct(){
$this->client = new Predis\Client();
}
public function set($key, $value){
$this->client->set($key, $value);
}
public function get($key){
return $this->client->get($key);
}
}
这里是使用这个包装器的简单代码 class :
$client = new CacheWrapper();
echo $client->get('key1');
这个 class 可以完美工作的问题是它在 class 内部创建了依赖项,我想通过将依赖项注入 class 而不是让 class 来创建它的依赖项,因此包装器 class 将如下所示:
class CacheWrapper {
private $client;
public function __construct(Predis\Client $predisObj){
$this->client = $predisObj;
}
public function set($key, $value){
$this->client->set($key, $value);
}
public function get($key){
return $this->client->get($key);
}
}
所以我必须编写以下代码来使用包装器 class :
$predis = new Predis\Client();
$client = new CacheWrapper($predis);
echo $client->get('key1');
但我认为没有必要使用包装器 class,因为我仍然在我的代码中使用原始的 class。所以我的问题是:依赖注入和包装器 class 概念是否相互矛盾并且不能一起使用,解决此类问题的最佳方法是什么?
当您确切知道要扩展的对象时,最好使用普通继承。
依赖注入适用于当您知道自己将 extending/using class 满足某些基本条件但可能超出此条件或由其他开发人员定义的情况。在那种情况下,您将代码设置为需要一个基础 class(或接口),并让您的 class 的用户确切地决定要扩展哪个实现。
tl;dr
如果您的 class 将始终用作:
$predis = new Predis\Client();
$client = new CacheWrapper($predis);
echo $client->get('key1');
然后依赖注入没有添加任何有用的东西。但是,如果它可能是:
$other = new OtherPredisLikeClass\Client();
$client = new CacheWrapper($other);
echo $client->get('key1');
然后依赖注入让你的 class 的用户无需重写你的 class.
就可以使用它As everybody knows, the point of wrapper classes is encapsulates the functionality of another class or component
这实际上并不准确。 "Wrapper Classes" 并不像你暗示的那么简单。有许多设计模式 "wrap" a class。
适配器模式 'wraps' 当所需的 API 与您拥有的 class 的 API 不匹配时的对象。
Facade 模式为更大的代码体提供了一个简化的接口。
Class A{
String setValueFirstHalf(String)
String setValueSecondHalf(String)
Void getValue()
}
// Pseudo-code for 'wrapper' that is an 'adapter pattern' impl.
// This class 'wraps' A and changes the API
Class WrapsA_Adapter{
String setFirst(String) {myA.setValueFirstHalf(String)}
String setSecond(String) {myA.setValueSecondHalf(String)}
Void get() {myA.getValue()}
}
// Pseudo-code for 'wrapper' that is an 'facade pattern' impl.
// This class 'wraps' A and changes the API to 'simplify' it.
// Often the 'facade pattern' uses several classes to do its task,
// but it 'can' use just one like we did below. (this example is obviously a stretch)
Class WrapsA_Facade{
String get()
Void set(String first, String second){
myA.setValueFirstHalf (first);
myA.setValueSecondHalf(second);
}
}
参见:Adapter pattern, Facade pattern
现在直接回答你的问题:
does dependency injection and wrapper class concepts goes against each other and can't be used together and what is the best way to solve issue like this ?
他们并不是天生对立的。
您可以很容易地拥有一个 WrapperFacade 实现,其中 Facade 注入了接口的 'specific' 实例。
如果适配器正在适配接口,并且您正在注入该接口的特定实现以供其使用,则具有依赖项注入的适配器模式也将有效。