Dependency made simple

June 27, 2008 by Bảo
Filed under: Programming 

Dependency Injection là một pattern cho phép người dùng đưa một lệ thuộc vào lớp / đối tượng. Hay nói cách khác là một phương pháp tách lệ thuộc của một lớp đối với một lớp khác. Có một bài viết do Martin Fowler viết, khá là dài dòng và phức tạp, nhưng thực tế nó lại rất đợn giản :D , thậm chí là nhiều người đã dùng mà không biết là mình dùng pattern này.

Có 3 phương pháp injection :

  1. Constructor Injection
  2. Setter Injection
  1. Interface Injection

Xét đoạn php như sau :

class Example
{
    private $_helper;
 
    public function __construct()
    {
        $this->_helper = new MyHelper();
    }
 
    public function doSomethiong()
    {
        $this->_helper->foo();
    }
}
 
interface MyHelper_Interface
{
    public function foo();
}
 
class MyHelper implements MyHelper_Interface
{
    public function foo()
    {
        echo 'Foo';
    }
}

Rõ ràng là Example bị lệ thuộc vào MyHelper thông qua khai báo. Sau đây sẽ tiến hành thay đổi code để thích hợp với các kiểu DI trên.

Constructor Injection

Đơn giản là truyền một đối tượng khi khởi tạo để xóa dòng khởi tạo trực tiếp lớp MyHelper.

class Example
{
    private $_helper;
 
    public function __construct(MyHelper_Interface $helper)
    {
        $this->_helper = $helper;
    }
 
    /* rest of the class is here */
}

Setter Injection

Cách thứ 2, dùng thông qua hàm set để inject helper vào, mục tiêu vẫn là hủy dòng khởi tạo trực tiếp.

class Example
{
    private $_helper;
 
    public function setHelper(MyHelper_Interface $helper)
    {
        $this->_helper = $helper;
    }
 
    /* rest of the class is here */
}

Interface Injection

Cách thứ 3 là phức tạp nhất, cách này dùng khi việc inject Helper này xảy ra thường xuyên nên đưa thành một interface luôn. Cái này thật ra chỉ là phiên bản Setter điều chỉnh lại :D

interface iInjectHelper
{
    public function injectHelper(MyHelper_Interface $helper);
}
 
class Example implements iInjectHelper
{
    private $_helper;
 
    public function injectHelper(MyHelper_Interface $helper)
    {
        $this->_helper = $helper;
    }
 
    /* rest of the class is here */
}

Kết luận

Hầu hết tất cả các phương pháp DI trên đều dùng để làm một việc là hủy việc khởi tạo trực tiếp lớp MyHelper, hay là xóa đi lệ thuộc của MyHelper đối với Example, tùy vào nhu cầu cụ thể mà dùng phương pháp Injection nào, nếu như class cần inject có quan hệ composition thì lúc đó phải dùng constructor injection, trong khi quan hệ chỉ là aggregation thì có thể dùng setter hoặc interface injection, chi tiết hơn thì có thể xem lại bài của Martin Fowler :)

Biên & Dịch từ đây

Comments

Tell me what you're thinking...
and oh, if you want a pic to show with your comment, go get a gravatar!





:D :) ^_^ :( :o :shock: 8) ;-( :lol: xD :wink: :evil: :p :whistle: :woot: :sleep: =] :sick: :straight: :ninja: :love: :kiss: :angel: :bandit: :alien: