IOC(inversion of control)的中文解釋是“控制反轉”或者“依賴注入”,它的實現目的是:我們可以通過配置文件來控制程序的流程,達到程序代碼的優化。初學者往往弄不清楚為什么我們可以通過“控制反轉”或“依賴注入”來優化我們的代碼。今天我想借這個機會說說我對IOC程序設計原則的認識,以及它是怎么樣把我們的程序弄“活”的。
一、名詞解釋
首先我想說說我對“控制反轉”和“依賴注入”的認識。
1、控制反轉:
對於初學者來說,我們平時寫代碼,“一段代碼會完全控制了程序的流程”,因為我們習慣於用new關鍵字來創建對象,再通過對象來調用它的方法。對於我們來說,這是再正常不過的了,可是如果此時我們的需求發生了一點改變,我們就不得不修改源代碼,這就是我們常講的“硬編碼(hard-coding)”,而修改源代碼是程序設計的大忌,這違反了程序設計的“開閉原則”,即對擴展是開放的,對修改是關閉的。
- //代碼示例:
- public class Animal {
- public void eat() {
- System.out.println(" 動物 吃東西了!");
- }
- }
- public class Pig extends Animal{
- public void eat() {
- System.out.println(" 小豬 吃東西了!");
- }
- }
- public class Dog extends Animal {
- public void eat() {
- System.out.println(" 小狗 吃東西了!");
- }
- }
- public class Project {
- public static void main(String[] args) {
- Animal pig = new Pig();
- pig.eat();
- }
- }
當我們寫完代碼時,我們的程序只能執行小豬吃東西,可是如果此時需求要求我們要小狗吃東西,是不是我們的代碼又要變了呢。此時我們引入了配置文件,我們事先在配置文件中已經配置好了該是誰吃東西,等到程序運行時,程序會讀取配置文件中的值通過反射機制創建一個我們需要的對象,再調用它的eat方法就ok了。這樣看來,我們程序的執行流程控制權是不是轉交給了配置文件了呢,而程序代碼自己卻成了被控制的對象,這就是實現了“控制反轉”了。
2、依賴注入:
在講依賴注入之前,我想先講一講依賴注入的三種實現方式。
(1)構造注入, 是通過構造器方法注入實例變量
- public class Car {
- public void move(){
- //••••
- }
- }
- public class People {
- private Car car;
- public People(Car car) {//構造注入
- this.car=car;
- }
- public void move(){
- car.move();
- }
- }
(2)設值注入,是通過setter方法注入實例變量
- public class People {
- private Car car;
- public People(Car car){//構造注入
- this.car=car;
- }
- public void setCar(Car car) {//設置注入
- this.car = car;
- }
- public void move(){
- car.move();
- }
- }
(3)接口注入,是通過接口方法注入實例變量
- public interface AbstractCar {
- public void move();
- }
- public class Car {
- public void move(){
- System.out.println("車開了");
- }
- }
- public interface AbstractPeople {
- public void move();
- }
- public class People {
- public void move(AbstractCar car){//接口注入
- car.move();
- }
- }
問題思考:依賴注入有什么作用呢?
此時我們還無法回答這個問題,可是當我們考慮到配置文件時,我們就豁然開朗了,不管是哪種注入方法,目的都是給我們的程序傳入一個實例變量。而這個實例變量我們可以事先在配置文件中配置,當程序運行時就可以讀取配置文件,通過反射機制來創建所需的對象了,如果此時我們的需求發生了變化,我們也只需改一下配置文件就ok了。這里有些人可能會認為這也修改了文件呀,為什么修改配置文件就可以了呢。呵呵,其實配置文件是不需要編譯的,我們可以隨時修改配置文件,而不需要通過更改一行源代碼的方法就實現了程序流程的控制。這就是ICO的妙處哦~
3、IOC容器
使用IOC后,我們不需要自己去創建某個類的實例,而由IOC容器去創建,當我們需要使用某個對象時,直接到容器中去獲取就可以了。現在已經有許多非常優秀的IOC容器,比如spring等。
二、綜合理解
最后我想用一個圖來表示我對IOC的理解