企业🤖AI Agent构建引擎,智能编排和调试,一键部署,支持私有化部署方案 广告
### **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. ~~~ <!-- lang: php --> 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: ~~~ <!-- lang:php --> 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``. > **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: ~~~ <!-- lang:php --> $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. 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.