美文网首页
依赖注入(DI),控制反转(IOC),依赖反转(依赖倒置/DIP

依赖注入(DI),控制反转(IOC),依赖反转(依赖倒置/DIP

作者: 張小明 | 来源:发表于2024-03-05 17:07 被阅读0次

    作为一个业余后端爱好者,虽然时不时会看spring和laravel的文档,但是一直对依赖注入和控制反转无法形成自己的理解。今天无意中又查找了些资料,有了新的理解。发现之前我想复杂了,因为spring和laravel对于依赖注入和控制反转的设计已经很完善,所以很难去抽丝剥茧依赖注入和控制反转到底是什么东西。

    正文开始
    • 假如我们现在要写一个“人”类,我们在“人”类里面有一个 “生成人头” 的方法, 下面是我们最初的样子
    class Person{
        String hairColor;
        String eyeColor;
    
        function generateHead(){
            hairColor = "green";
            eyeColor = "yellow";
        }
    }
    
    • 后来我们通过简单的面向对象思维,把它单独交给一个头类Head来完成
    class Head{
        String hairColor;
        String eyeColor;
        __construct(String hColor, String eColor){
            hairColor = hColor;
            eyeColor = eColor;
        }
    }
    
    class Person{
        Head head;
        function generateHead(){
            head = new Head(hairColor: "green", eyeColor: "yellow");
        }
    }
    
    • 但是我们的头类依然在生成头方法中去初始化,这很不灵活,所以我们在生成头的方法中设置一个“头”这个参数,允许从外部传入“头”
    class Head{
        String hairColor;
        String eyeColor;
        __construct(String hColor, String eColor){
            hairColor = hColor;
            eyeColor = eColor;
        }
    }
    
    class Person{
        Head head;
        function generateHead(Head h){
            head = h;
        }
    }
    
    class PersonFactory{
        makePerson(){
            Head a = new Head(hairColor: "green", eyeColor: "yellow");
            Person p = new Person();
            p.generateHead(a);
        }
    }
    

    这时候已经完成了控制反转,这里的控制指的是“初始化这个头”的操作,反转指的是“进行这个操作的地点发生了变化”。
    之前是在“人”类里面完成,现在是谁调用方法,谁完成,这就是控制反转。
    而方法传参属于依赖注入的其中一种方式,这里我们通过依赖注入实现了控制反转。

    QA
    那我们实际在laravel或者spring框架中见到的实现方式为什么不是这个样子呢?
    因为框架中使用IOC容器,实现了自动依赖注入,所以不用再像我们这般去进行手动依赖注入的操作。

    好了,到这里依赖注入和控制反转就讲完了,是不是很简单的一个东西,其实这只是面向对象思维中,关于一个具体的实现细节的规定,平时可能大家都在使用这种规则,但当专门拿出来说这是什么的时候,我们并不能把名字和操作细节对应上,但其实是很简单的一个概念,而我们很多时候称这类操作为“组合”,“工厂模式”

    现在新的挑战出现了,当我们要使用生成头的时候,我们只能生成固定样式地头,假如有一天我们想让人长一个“铁头”,“鸡头”,“乌龟头”的时候,我们就需要去修改Person类,这是耦合的表现,所以依赖反转(依赖倒置/DIP)思维出现了

    Interface Head{
        setColors(String hColor, String eColor);
    }
    
    class IronHead implement Head{
        String hairColor;
        String eyeColor;
        
        setColors(String hColor, String eColor){
            hairColor = hColor;
            eyeColor = eColor;
        }
    
       breakDoor(){
          
       }
    }
    
    
    class ChickenHead implement Head{
        String hairColor;
        String eyeColor;
        
        setColors(String hColor, String eColor){
            hairColor = hColor;
            eyeColor = eColor;
        }
    
       crow(){
          
       }
    }
    
    
    class TurtleHead implement Head{
        String hairColor;
        String eyeColor;
        
        setColors(String hColor, String eColor){
            hairColor = hColor;
            eyeColor = eColor;
        }
    
       makeYouCry(){
          
       }
    }
    
    
    class Person{
        Head head;
        function generateHead(Head h){
            head = h;
        }
    }
    
    class PersonFactory{
        makeIronPerson(){
            Head a = new IronHead(hairColor: "green", eyeColor: "yellow");
            Person p = new Person();
            p.generateHead(a);
        }
    
        makeChickenPerson(){
            Head a = new ChickenHead(hairColor: "yellow", eyeColor: "brown");
            Person p = new Person();
            p.generateHead(a);
        }
    
        makeTurtlePerson(){
            Head a = new TurtleHead(hairColor: "yellow", eyeColor: "brown");
            Person p = new Person();
            p.generateHead(a);
        }
    }
    

    好了,现在我们想创造不同头的人,不再需要依赖修改Person类了,只需要添加一个想要的头实现Head接口,然后直接组装就可以了。这里我们选择依赖抽象的接口Head,而不是具体的实现,这就是依赖反转(依赖倒置/DIP)。而我们通常称为面向接口编程,抽象之类的

    相关文章

      网友评论

          本文标题:依赖注入(DI),控制反转(IOC),依赖反转(依赖倒置/DIP

          本文链接:https://www.haomeiwen.com/subject/adsdzdtx.html