码迷,mamicode.com
首页 > 其他好文 > 详细

听 Fabien Potencier 谈Symfony2 之 《What is Dependency Injection ?》

时间:2014-08-06 17:21:51      阅读:370      评论:0      收藏:0      [点我收藏+]

标签:blog   http   使用   os   io   数据   art   ar   

什么是依赖注入?
从PHP实现角度来分析依赖注入,因为PHP主要用于web开发,所以我们就看Web应用例子。
为了克服HTTP协议的无状态性,web应用程序需要有一个途径来在web请求之间存储用户信息。最简单的方式是使用cookie或者采用更好一点的PHP内建的Session机制。

$_SESSION[‘language‘]=‘en‘;

上面这句代码就实现了把语言存储到Session变量language里。从此之后,同一用户一些后续的请求都可以使用这个值了。因为$_SESSION 数组是个全局的变量。调用方式如下:

$user_language = $_SESSION[‘language‘];

因为依赖注入是面向对象世界里的概念,现在我们需要把PHP Session机制封装到一个类里面,然后应用到web应用程序中。

bubuko.com,布布扣
class SessionStorage
{
   function __construct($cookieName = ‘PHP_SESS_ID‘)
   {
    session_name($cookieName);
    session_start();
   }
   
   function set($key, $value)
   {
    $_SESSION[$key] = $value;
   }

   function get($key)
   {
    return $_SESSION[$key];
   }

   //...
}
bubuko.com,布布扣

接下来我们定义一个User类,来提供它的更高级的接口。

bubuko.com,布布扣
class User
{
    protected $storage;
    
    function __construct()
    {
    $this->$storage = new SessionStorage();
    }
    
    function setLanguage($language)
    {
    $this->storage->set(‘language‘, $language);
    }

    function getLanguage()
    {
    return $this->storage->get(‘language‘);
    }
   
    //.....
}
bubuko.com,布布扣

之后,我们就可以直接使用了。

$user = new User();
$user->setLanguage(‘en‘);
$user_language = $user->getLanguage();

如果做得更加灵活一点呢?你想改变会话cookie的名字怎么办?有几个方式:可以在User类中在SessionStorage的构造函数中指定,即一种硬编码方式。

bubuko.com,布布扣
class User
{
   function __construct()
   {
      $this->storage = new SessionStorage(‘SESSION_ID‘);
   }
   //....
}
bubuko.com,布布扣

      或者在User类外面定义一个常量:STORAGE_SESSION_NAME 这种全局式的常量定义,不推荐。

bubuko.com,布布扣
class User
{
  function __construct()
  {
    $this->storage = new SessionStorage(STORAGE_SESSION_NAME);
  }
 
  // ...
}

define(‘STORAGE_SESSION_NAME‘,‘SESSION_ID‘);
bubuko.com,布布扣

一种方式是把Session名作为User 类构造函数的参数:

bubuko.com,布布扣
class User
{
  function __construct($sessionName)
  {
    $this->storage = new SessionStorage($sessionName);
  }
 
  // ...
}
 
$user = new User(‘SESSION_ID‘);
bubuko.com,布布扣

    还有一种方式是PHP代码中常见的为Session存储类添加一个可选设置项数组options 

bubuko.com,布布扣
class User
{
  function __construct($storageOptions)
  {
    $this->storage = new SessionStorage($storageOptions[‘session_name‘]);
  }
 
  // ...
}
 
$user = new User(array(‘session_name‘ => ‘SESSION_ID‘));
bubuko.com,布布扣

实现的方法有很多啊,无论是硬编码,设置为常量,作为构造函数的参数还是可选项数组都不是最佳选择。虽然后两者看起来好那么一点点,但它让User类的构造器堆积了一些跟自己没关系的参数。

继续,另外一个问题又来了,如果我想改变SessionStorage类怎么办?比如在测试时,制造个假数据。或者你想把Session保存到数据库或者内存中时,就需要改变SessionStorage类了。就目前情况来看,如果不修改User类是不可能实现改变SessionStorage类的。

现在我们考虑依赖注入,我们不在User类中创建SessionStorage对象,而是在外部创建后作为User类的构造方法参数传递给User对象。

bubuko.com,布布扣
class User
{
  function __construct($storage)
  {
    $this->storage = $storage;
  }
 
  // ...
}
bubuko.com,布布扣

OK,这就是依赖注入,没别的了!现在再使用User类时可能需要比上次麻烦一点:

$storage = new SessionStorage(‘SESSION_ID‘);
$user = new User($storage);

现在在不改变User类的前提下,改变Session名字,改变SessionStorage类,你想干啥都行了!

总结一下:依赖注入是组件们通过他们的构造器,方法,或者属性字段来获取他们依赖的对象。

构造器注入:

bubuko.com,布布扣
class User
{
  function __construct($storage)
  {
    $this->storage = $storage;
  }
 
  // ...
}
bubuko.com,布布扣

设置器注入(方法注入):

bubuko.com,布布扣
class User
{
  function setSessionStorage($storage)
  {
    $this->storage = $storage;
  }
 
  // ...
}
bubuko.com,布布扣

属性字段注入:

class User
{
  public $sessionStorage;
}
 
$user->sessionStorage = $storage;

这些在Symfony 中你都会看到他们的身影:

构造注入:

$dispatcher = new sfEventDispatcher();
$storage = new sfMySQLSessionStorage(array(‘database‘ => ‘session‘, ‘db_table‘ => ‘session‘));
$user = new sfUser($dispatcher, $storage, array(‘default_culture‘ => ‘en‘));

将$dispatcher对象和$storage对象注入到$user对象中。

方法注入:

bubuko.com,布布扣
$transport = new Zend_Mail_Transport_Smtp(‘smtp.gmail.com‘, array(
  ‘auth‘     => ‘login‘,
  ‘username‘ => ‘foo‘,
  ‘password‘ => ‘bar‘,
  ‘ssl‘      => ‘ssl‘,
  ‘port‘     => 465,
));
 
$mailer = new Zend_Mail();
$mailer->setDefaultTransport($transport);
bubuko.com,布布扣

该注入俗称为setter注入。

Ok,这就是依赖注入了,它会在Symfony2中发展到服务容器注入。 以提供更加方便灵活松散耦合的多级依赖管理。它就是Service Container,它为Symfony2的执行效率和可扩展性提供了最强大的支持。

听 Fabien Potencier 谈Symfony2 之 《What is Dependency Injection ?》,布布扣,bubuko.com

听 Fabien Potencier 谈Symfony2 之 《What is Dependency Injection ?》

标签:blog   http   使用   os   io   数据   art   ar   

原文地址:http://www.cnblogs.com/huidaoli/p/3894501.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
分享档案
周排行
mamicode.com排行更多图片
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!