【问题标题】:wrapper classes and dependency injection包装类和依赖注入
【发布时间】:2015-12-18 22:55:48
【问题描述】:

众所周知,包装类的重点是封装另一个类或组件的功能。这是一个简单的类,它包装了一小部分 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');

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

【问题讨论】:

    标签: php design-patterns dependency-injection wrapper


    【解决方案1】:

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

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

    当所需的 API 与您拥有的类的 API 不匹配时,适配器模式会“包装”一个对象。

    外观模式为大量代码提供了一个简化的接口。

    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


    现在直接回答你的问题:

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

    他们并没有天生对立。

    你可以很容易地拥有一个 WrapperFacade 实现,其中 Facade 被注入了一个接口的“特定”实例。

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

    【讨论】:

      【解决方案2】:

      当您确切知道要扩展的对象时,最好使用普通继承。

      依赖注入适用于当您知道自己将扩展/使用满足某些基本标准但可能不止这些标准或由其他开发人员定义的类时。在这种情况下,您将代码设置为需要一个基类(或接口),并让您的类的用户准确决定要扩展哪个实现。

      tl;dr

      如果你的班级总是被用作:

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

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

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

      然后依赖注入让你的类的用户在不重写你的类的情况下使用它。

      【讨论】:

        猜你喜欢
        • 2011-07-18
        • 1970-01-01
        • 2011-03-16
        • 2012-03-20
        • 1970-01-01
        • 2021-11-19
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多