PHP设计模式之——依赖注入

依赖注入(dependency injection)是实现控制反转的一种技术,顾名思义,就是将依赖(被调用者)注入给依赖对象(调用者)。

用户类User有一个注册方法,我们需要实现一个功能,在注册成功后,给用户发送一封邮件通知。我们先写一个发送邮件的类:

class EmailClass
{
    public function sendEmail($username, $email)
    {
        print_r("send register email to:" . $email . PHP_EOL);
    }
}

然后在用户注册方法中实例化一个邮件类:

class User
{
    private $username;
    private $password;
    private $mobile;
    private $email;

    public function register()
    {
        // 注册逻辑
        // .........

        // 发送邮件逻辑
        $emailClass = new EmailClass();
        $emailClass->sendEmail($this->username, $this->email);
    }
}

这时候又来一个需求,需要在注册成功之后给用户发送短信,于是又要在注册方法里面实例化一个发送短信的类。或者这个时候我们要改一下邮件内容,要把注册密码发给用户,于是我们要给EmailClass::sendEmail加一个password参数。经过长期迭代和添油加醋,我们需要频繁的去修改核心注册逻辑,最终的注册方法将变得极为臃肿且难以维护。

下面我们使用依赖注入来优化一下这段代码,首先定义一个用于发送注册通知的interface

abstract class RegisterNotify
{
    abstract public function send(User $user);
}

分别实现发送邮件和短信的类:

class RegisterNotifyEmail extends RegisterNotify
{
    public function send(User $user)
    {
        echo "send register email to:" . $user->email . PHP_EOL;
    }
}

class RegisterNotifySms extends RegisterNotify
{
    public function send(User $user)
    {
        echo "send register sms to:" . $user->mobile . PHP_EOL;
    }
}

实现用户注册方法:

class User
{
    public $username;
    public $password;
    public $mobile;
    public $email;
    public $notifyList = [];

    public function __construct($username, $password, $mobile, $email)
    {
        $this->username = $username;
        $this->password = $password;
        $this->mobile = $mobile;
        $this->email = $email;
    }

    public function setNotify(RegisterNotify $notify)
    {
        $this->notifyList[] = $notify;
    }

    public function register()
    {
        // 注册逻辑
        // .........

        // 发送通知逻辑
        foreach ($this->notifyList as $notify) {
            $notify->send($this);
        }
    }
}

最后我们通过如下逻辑来调用:

$user = new User('lilei', '123456', '13111111111', 'lilei@gmail.com');
$user->setNotify(new RegisterNotifyEmail($user));
$user->setNotify(new RegisterNotifySms($user));
$user->register();

将依赖通过参数从外部业务逻辑处传入,用户类只需要依赖于RegisterNotify这一抽象类,并不需要关心具体的通知逻辑是如何实现的,也不需要关心有多少通知。业务逻辑根据需求将不同的消息通知注入到用户类中,而不需要每一次都去修改核心注册逻辑。

常见的依赖注入方式大致可分两种:

  • 方法注入:包括构造方法、成员方法和静态方法传参

  • set属性注入:直接将依赖关系赋值给对象属性

作为一种极为流行的设计模式,依赖注入在各大主力语言中都有着非常广泛的应用,比如PHP的Laravel、Java的Spring,可以充分解耦代码逻辑,提高了代码的可读性和可扩展性。

暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇