包装类和依赖注入

时间:2015-12-18 22:55:49

标签: php design-patterns dependency-injection wrapper

众所周知,包装类的重点是封装另一个类或组件的功能。这是一个包含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);

}

 }

以下是使用此包装类的简单代码:

$client = new CacheWrapper();
echo $client->get('key1');

这个类可以完美地解决它在类中创建依赖项的问题,我希望通过将依赖项注入类而不是让类创建其依赖项来避免它,因此包装类看起来像这样:

    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);

}

 }

所以我必须编写以下代码来使用包装类:

    $predis = new Predis\Client();
    $client = new CacheWrapper($predis);
    echo $client->get('key1');

但我认为没有必要使用包装类,因为我仍然在我的代码中使用原始类。所以我的问题是:依赖注入和包装类概念是否相互冲突,不能一起使用,解决这类问题的最佳方法是什么?

2 个答案:

答案 0 :(得分:1)

  

众所周知,包装类的要点是封装了   另一个类或组件的功能

这实际上并不准确。 “包装类”并不像你暗示的那么简单。有许多设计模式可以“包装”一个类。

当所需的API与您拥有的类的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 patternFacade pattern

现在直接回答你的问题:

  

依赖注入和包装类概念是否违背每一个   其他的,不能一起使用,最好的解决方法是什么   像这样的问题?

他们本身并不相互对立。

您可以非常轻松地使用WrapperFacade实现,其中Facade注入了接口的“特定”实例。

如果适配器正在调整接口,并且您正在注入该接口的特定实现以供其使用,则具有依赖项注入的适配器模式也将是有效的。

答案 1 :(得分:0)

如果您确切知道要扩展的对象,那么最好使用普通继承。

依赖注入是指当您知道将扩展/使用满足某些基本条件的类时,但可能超过或由其他开发人员定义的类。在这种情况下,您将代码设置为需要基类(或接口),并让您的类的用户确切地确定要扩展的实现。

<强> TL;博士

如果您的课程将始终用作:

$predis = new Predis\Client();
$client = new CacheWrapper($predis);
echo $client->get('key1');

然后依赖注入不添加任何有用的东西。但是,如果它可能是:

$other = new OtherPredisLikeClass\Client();
$client = new CacheWrapper($other);
echo $client->get('key1');

然后,依赖注入允许您的类的用户使用它而无需重写您的类。