Taking It Further 更进一步

Let's consider another example to solidify our understanding. Perhaps we want to notify customers of charges to their account. We'll define two interfaces, or contracts. These contracts will gie us the flexibility to change out their implementations later.

让我们考虑另一个例子来巩固理解。 可能我们想要去提醒用户该交钱了。 我们会定义两个接口,或者约定。这些约定使我们在更改实际实现时更加灵活。

interface BillerInterface {
    public function bill(array $user, $amount);

interface BillingNotifierInterface {
    public function notify(array $user, $amount);

Next we'll build an implementation of our BillerInterface contract:

接下来我们要写一个 BillerInterface 的实现:

class StripeBiller implements BillerInterface{
    public function __construct(BillingNotifierInterface $notifier)
        $this->notifier = $notifier;
    public function bill(array $user, $amount)
        // Bill the user via Stripe...
        $this->notifier->notify($user, $amount);

By separating the responsibilities of each class, we're now able to easily inject various notifier implementations into our billing class. For example, we could inject a SmsNotifier or an EmailNotifier. Our biller is no longer concerned with the implementation of notifyingg, but only the contract. As long as a class abides by its contract (interface), the biller will gladly accept it. Furthermore, not only do we get added flexibility, we can now test our biller in isolation from our notifiers by injecting a mock BillingNotifierInterface.

只要遵守了每个类的责任划分,我们很容易将不同的提示器(notifier)注入到账单类里面。 比如,我们可以注入一个 SmsNotifier 或者 EmailNotifier。账单类只要遵守了约定,就不用再考虑如何实现提示功能。只要是遵守约定(接口)的类, 账单类都能用。这不仅仅是方便了我们的开发,而且我们还可以通过模拟 BillingNotifierInterface 来进行无痛测试。

Be The Interface 使用接口

While writing interfaces might seem to a lot of extra work, they can actually make your development more rapid. Use interfaces to mock and test the entire back-end of your application before writing a single line of implementation!


So, how do we do dependency injection? It's simple:


$biller = new StripeBiller(new SmsNotifier);

That's dependency injection. Instead of the biller being concerned with notifying users, we simply pass it a notifier. A change this simple can do amazing things for your applications. Your code immediately becomes more maintainable since class responsibilities are clearly delineated. Also, testability will skyrocket as you can easily inject mock dependencies to isolate the code under test.

这就是依赖注入。 biller 不需再考虑提醒用户的事儿,我们直接传给他一个提示器(notifier)。 这种微小的改动能使你的应用焕然一新。 你的代码马上就变得更容易维护, 因为明确指定了类的职责边界。 并且更容易测试,你只需使用模拟依赖即可。

But what about IoC containers? Aren't they necessary to do dependency injection? Absolutely not! As we'll see in the following chapters, containers make dependency injection easier to manage, but they are not a requirement. By following the principles in this chapter, you can practice dependency injection in any of your projects, regardless of whether a container is avaliable to you.

那 IoC 容器呢? 难道依赖注入不需要 IoC 容器么?当然不需要!在接下来的章节里面你会了解到,容器使得依赖注入更易于管理,但是容器不是依赖注入所必须的。只要遵循本章提出的原则,你可以在你任何的项目里面实施依赖注入,而不必管该项目是否使用了容器。

results matching ""

    No results matching ""