## 依赖注入 > 1、构造函数注入 为邮件服务定义抽象层 `EmailSenderInterface` ```php interface EmailSenderInterface { public function send(); } ``` 定义`Gmail`邮件服务 ```php class GmailSender implements EmailSenderInterface { // 实现发送邮件的类方法 public function send() { // TODO: Implement send() method. echo __CLASS__; } } ``` 定义`Tencent`邮件服务 ```php class TencentSender implements EmailSenderInterface { // 实现发送邮件的类方法 public function send() { // TODO: Implement send() method. echo __CLASS__; } } ``` 定义评论类 ```php class Comment { // 用于引用发送邮件的库 private $_eMailSender; // 构造方法注入 public function __construct(EmailSenderInterface $emailSender) { $this->_eMailSender = $emailSender; } // 保存评论 public function save() { $this->afterInsert(); } // 当有新的评价,即 save() 方法被调用之后中,会触发以下方法 protected function afterInsert() { $this->_eMailSender->send(); // 发送邮件 } } ``` 实例化两种不同的邮件服务,当然,他们都实现了`EmailSenderInterface` ```php // 用构造函数将GmailSender注入 $comment1 = new Comment(new GmailSender()); // 使用Gmail发送邮件 $comment1->save(); // GmailSender // 用构造函数将MyEmailSender注入 $comment2 = new Comment(new TencentSender()); // 使用TencentSender发送邮件 $comment2->save(); // TencentSender ``` >上面的代码,解决了`Comment`类对于`GmailSender`等具体类的依赖,通过构造函数,将相应的实现了 `EmailSenderInterface`接口的类实例传入`Comment`类中,使得`Comment`类可以适用于不同的邮件服务。 从此以后,无论要使用何何种邮件服务,只需写出新的`EmailSenderInterface`实现即可, `Comment`类的代码不再需要作任何更改,扩展起来、测试起来都省心省力。 ###### 参考文献 1、[Yii2.0 依赖注入容器(Dependency Injection Container)](https://www.yiichina.com/doc/guide/2.0/concept-di-container) 2、[Yii2.0 依赖注入(DI)和依赖注入容器的原理](https://www.yiichina.com/tutorial/112)