Spring核心之一:IOC

    IOC(Inversion of Control)其实是一种思想,这种思想并不是Spring独有的,而是在软件开发中,大家提出的一种开发原则,类似面向接口编程原则、开闭原则等。

    网上有很多类似的文章尝试去通俗易懂地解释IOC思想,这里我根据自己的理解尝试去解释一下这个概念,看下面这个类:

public class Car {
    private Wheel wheel;
    /**
     * Car类的run方法,其实是需要调用Wheel的turn方法来完成
     * 汽车的奔跑是依赖轮子的转动
     */
    public void run(){
        wheel.trun();
    }
}
public interface Wheel {
    void trun();
}

Car类run()方法的执行,是依赖另外一个接口Wheel,这里肯定有小伙伴问,为什么Wheel是定义成一个接口呢?这其实是我们Java编程的另外一个原则的体现——面向接口编程。run()方法的内容,并不关心是什么轮子来转动,只知道轮子能转就行,至于是前驱轮子转、后驱轮子转,还是前后驱都转,Car类并不关心。换句话说,Wheel接口的实现类是什么,Car类并不关心,所以没有必要在Car类中定义具体的实现,只需要定义一个Wheel接口就可以了。

现在想要实现面向接口编程我们只差Wheel接口的实现类了:

/**
 * 前驱轮的实现
 */
public class PrecursorWheel implements Wheel{
    @Override
    public void trun() {
        System.out.println("precursor trun!");
    }
}

我们新建了一个 Wheel接口 的实现类PrecursorWheel。但是这样很明显还不够,因为目前Car 类的 wheel成员变量还是个空引用,并没有关联PrecursorWheel的实现类呢。于是我们第一反应是这样改代码:

public class Car {
    private Wheel wheel;
    /**
     * Car类的run方法,其实是需要调用Wheel的turn方法来完成
     * 汽车的奔跑是依赖轮子的转动
     */
    public void run(){
        wheel = new PrecursorWheel();//wheel指向PrecursorWheel前驱轮实现类
        wheel.trun();
    }
}

然后我们可以实例化一个Car类,然后让Car真正跑起来了,写个测试类(main方法就行)测一下:

public static void main(String[] args) {
        Car car = new Car();
        car.run();
}

测试结果就不贴了,Java新手脑补也能知道,But,如果这时候,客户说我不想要 前驱的车了,我要个后驱的车,咋办咧?简单!增加一个实现类:
 

/**
 * 后驱轮子的实现类
 */
public class RearWheel implements Wheel{
    @Override
    public void trun() {
        System.out.println("rear trun!");
    }
}

然后改造Car类:

public class Car {
    private Wheel wheel;

    /**
     * Car类的run方法,其实是需要调用Wheel的turn方法来完成
     * 汽车的奔跑是依赖轮子的转动
     */
    public void run(){
        wheel = new RearWheel();wheel指向RearWheel后驱轮实现类
        wheel.trun();
    }

    public static void main(String[] args) {
        Car car = new Car();
        car.run();
    }
}

这样Car类的实例,就变成了后轮驱动的Car对象了。
上面的编码风格用其特点就是如下:

目标类(Car类)中直接实例化其依赖接口的实现类(RearWheel、PrecursorWheel);

虽然我们的例子中只有 Car类依赖Wheel接口,但以后可能会有Truck类、Bicycle类....等很多类依赖Wheel接口,Wheel接口的实现类有一点点变动,依赖于它的类都要相应修改,这是牵一发而动全身的修改。

显然,问题就出在  Car 类中  这句代码上:wheel = new RearWheel();

这种硬编码的方式,让Car类与RearWheel类耦合了。

那么如何处理这样讨人厌的代码呢?大家就说,那就在程序种单独找一个第三方来管理类似这种wheel = new RearWheel()代码吧,这种思想就叫 IOC。

抽象总结出来就是:某一接口(如Wheel接口)具体实现类的选择权,从目标依赖类(如Car类)中移除,交由第三方来完成。这种思想就称为 IOC。 本例子中实现如下:

新建一个第三方类WheelManager,来专门管理 Wheel接口的实现类实例,所有与Wheel接口依赖的类,都通过第三方来得到想要的实例:

public class WheelManager {
    public static Wheel acquireWheel(String name){
        if("rear".equals(name)){
            return new RearWheel();
        }
        return new PrecursorWheel();
    }
}

Car类改造:

public class Car {
    private Wheel wheel;
    /**
     * Car类的run方法,其实是需要调用Wheel的turn方法来完成
     * 汽车的奔跑是依赖轮子的转动
     */
    public void run(){
        wheel = WheelManager.acquireWheel("rear");
        wheel.trun();
    }
}

如果还有 Truck类、Bicycle类,也类似:

public class Truck {
    private Wheel wheel;
    public void truckRun(){
        wheel = WheelManager.acquireWheel("");
        wheel.trun();
    }
}
public class Bicycle {
    private Wheel wheel;
    public void bicycleRun(){
        wheel = WheelManager.acquireWheel("rear");
        wheel.trun();
    }
}

上述就是一种简单的 IOC思想(控制反转)的实现方式:WheelManager变成了轮子的管理中心,所有Wheel接口的实现类实例,都交由它来管理。Car、Truck、Bicycle等具体的业务类,都通过WheelManager间接来与其要依赖的类进行耦合。

对控制反转的理解:
控制:指定Car类的Wheel成员变量是Wheel接口哪个实现类的实例,这个控制权。
反转:上述的控制权,不在Car类定义中去指定,而是交由第三方(WheelManager)来决定。

你可能感兴趣的:(Spring学习笔记)