• 前端——什么是依赖注入与控制反转


    还是Angular官网讲的清楚
    依赖注入 - ts - GUIDE

    依赖注入

    有一个函数,在实现的时候需要依赖别的方法一起作用,来实现功能,例如:

    1. function returnRandom () {
    2. return 1;
    3. }
    4. function returnUserName () {
    5. return 'TEST';
    6. }
    7. /** main函数依赖returnRandom和returnUserName来实现功能 */
    8. function main () {
    9. const random = returnRandom();
    10. const userName = returnUserName();
    11. return random + userName;
    12. }
    13. main();

            此时main函数和returnRandom、returnUserName紧密耦合,当returnRandom需要传入一个参数时(即函数实现出现变更时)main函数的实现也需要变更,尤其是当这个参数需要从main接收再传入到returnRandom时,代码的变更变得更加复杂、容易出错。

    1. function returnRandom (param) {
    2. return 1 + param;
    3. }
    4. function returnUserName () {
    5. return 'TEST';
    6. }
    7. /** main函数依赖returnRandom和returnUserName来实现功能 */
    8. function main (param) {
    9. const random = returnRandom(param);
    10. const userName = returnUserName();
    11. return random + userName;
    12. }
    13. main(Math.random());

            当returnRandom和returnUserName不在main函数内部实现,而是作为参数传入main函数时,main、returnRandom、returnUserName就解耦了,main的实现不再依赖returnRandom和returnUserName。

    1. function returnRandom () {
    2. return 1;
    3. }
    4. function returnUserName () {
    5. return 'TEST';
    6. }
    7. function main (random, userName) {
    8. return random + userName;
    9. }
    10. main(returnRandom(), returnUserName());

            returnRandom和returnUserName的实现变更时,不会影响到main的实现。

    1. function returnRandom (param) {
    2. return 1 + param;
    3. }
    4. function returnUserName (nickName) {
    5. return 'TEST' + nickName;
    6. }
    7. function main (random, userName) {
    8. return random + userName;
    9. }
    10. main(returnRandom(Math.random()), returnUserName('nickName'));

             这就是依赖注入,逻辑的实现有外部依赖时,将依赖通过外部传入的方式注入,而非在逻辑内部直接定义并使用外部依赖,这有助于代码的解耦和测试。为什么有助于测试呢?因为现在我们对它的依赖有了完全的控制权,我们可以直接创建一些mock数据测试逻辑。如果未使用依赖注入,我们可能需要使用一些难以维护的方式来测试逻辑(例如注释代码实现后填入mock数据,测试完成后再还原代码)。

    1. function returnRandom (param) {
    2. return 1 + param;
    3. }
    4. function returnUserName (nickName) {
    5. return 'TEST' + nickName;
    6. }
    7. function main (random, userName) {
    8. return random + userName;
    9. }
    10. /** 原代码实现 */
    11. main(returnRandom(Math.random()), returnUserName('nickName'));
    12. /** 当你需要测试main函数时 */
    13. const mockRandom = NaN;
    14. const userName = null;
    15. main(mockRandom, userName);

    控制反转

             使用依赖注入后,代码优雅解耦,但是这对于编写和阅读代码的人来说就有点痛苦了,尤其是依赖多、依赖复杂的情况下,代码变得难以阅读。那我们能不能让依赖注入这件事自动完成?这就要使用控制反转了:借助于“第三方”实现具有依赖关系的对象之间的解耦。

            简单来说就是把一些事交给框架来做,例如react、vue实现的更新机制,在数据变更时自动对真实dom进行最小化的更改,而没有控制反转的话,我们就需要使用vanilla js、jquery,在数据变更的同时,手动地查找dom、拼接数据、更新dom。

            依赖注入也是可以如此,使用者只需要在代码中定义想要注入的依赖,由框架层完成依赖的创建、注入。具体实现不描述,很多库有示例:

    1. @Injectable
    2. class Food {}
    3. @Injectable
    4. class Bark {}
    5. /** Eat依赖Food */
    6. @Injectable
    7. class Eat {
    8. constructor (private food: Food) {}
    9. }
    10. /** Dog依赖Bark和Eat */
    11. @Injectable
    12. class Dog {
    13. /** 定义需要的依赖,由框架层自动注入 */
    14. constructor (private eat: Eat, private bark: Bark) {}
    15. wantSomeFood () {
    16. this.bark.call();
    17. }
    18. }

  • 相关阅读:
    Python算法——树的直径
    颜表情记录(自用
    【论文阅读】自动作文评分系统:一份系统的文献综述
    【OpenCV 例程 300篇】249. 特征描述之视网膜算法(FREAK)
    C#创建ini文件写入并读取
    【无标题】
    【Java SE】数据类型常见错误及字符串拼接与转换
    焕新出发,利尔智达天下
    PostgreSQL实战之物理复制和逻辑复制(三)
    Shell命令笔记2
  • 原文地址:https://blog.csdn.net/weixin_48003149/article/details/136834209