2010-01-08 4 views
4

после прочтения this вопрос я интересно, если кто-то может мне помочь понять, как реализовать правильно Dependency Injection с этими PHP классов:Dependency Injection простая реализация

class DBClass 
{ 
    private $mMysqli; 
    function __construct(mysqli $database) 
    { 
     $this->mMysqli=$database; 
    } 
    function __destruct() 
    { 
     $this->mMysqli->close(); 
    } 

    public function listUsers() 
    { 
     $query='SELECT * FROM Utente;'; 
     $resultset=$this->mMysqli->query($query); 
     while($row = $resultset->fetch_array(MYSQLI_ASSOC)) { 
      echo $row['username']; 
      echo $row['pwd']; 
      echo "<br />\n"; 
     } 

    } 

    public function runQuery($query) 
    { 
     return $resultset=$this->mMysqli->query($query); 
    } 

    public function getConnection() 
    { 
     return $this->mMysqli; 
    } 
} 

класс Session:

class Session 
{ 
    private $_session; 
    public $maxTime; 
    private $database; 

    public function __construct(DBClass $database) 
    { 
     $this->database=$database; 
     $this->maxTime['access'] = time(); 
     $this->maxTime['gc'] = get_cfg_var('session.gc_maxlifetime'); 
     session_set_save_handler(array($this,'_open'), 
       array($this,'_close'), 
       array($this,'_read'), 
       array($this,'_write'), 
       array($this,'_destroy'), 
       array($this,'_clean') 
       ); 
     register_shutdown_function('session_write_close'); 
     session_start(); 
     ... 
    } 
} 

Класс пользователя (для получения подробной информации о пользователе, зарегистрированном в настоящее время):

class User 
{ 
    private $username; 
    private $role; 
    private $session; 

    function __construct($session) 
    { 
     $this->session=$session; 
     ... 
    } 
} 

Внешность:

$connection=new mysqli(DB_HOST, DB_USER, DB_PASSWORD, DB_DATABASE); 
$database=new DBClass($connection); 
$session=new Session($database); 
$user=new User($session); 

Это правильный способ?

ответ

9

Да. Теперь вы вводите зависимости через конструктор, который обеспечивает меньшую связь. Теперь вы можете легко заменить эти зависимости, например. когда UnitTesting вы можете заменить их на Mocks.

У вас есть некоторая связь, хотя с использованием конкретного DBClass как TypeHint вместо interface. Поэтому, когда вы захотите использовать другой DBClass, его нужно будет назвать DBClass. Вы могли бы достичь более короткого сцепления на coding against an interface, чтобы вместо этого реализовать конкретные классы.

Чтобы создать только отдельные экземпляры класса (как указано в комментариях), вы можете использовать Singleton (например, предложенный Кевином Пено) или Factory для создания и отслеживания, если экземпляр был создан еще. Или используйте контейнер службы DI, который похож на завод, но не то же самое. Он создает и управляет объектами для вас.

Symfony Components library has a Dependency Injection Container с отличной документацией и знакомство с темой о том, как еще больше улучшить DI с помощью Сервисных контейнеров. Контейнеры также могут использоваться для ограничения экземпляров. Проверьте это.

+0

+1 для существующих систем/библиотек –

+0

+1 для упоминания интерфейсов – rick

+0

Спасибо за ответ, но как я могу использовать DI для создания экземпляра только одного экземпляра объекта, например, для подключения к базе данных? –