如果一个类A的功能实现需要借助于类B,那么就称类B是类A的依赖,如果在类A的内部去实例化类B,那么两者之间会出现较高的耦合,一旦类B出现了问题,类A也需要进行改造,如果这样的情况较多,每个类之间都有很多依赖,那么就会出现牵一发而动全身的情况,程序会极难维护,并且很容易出现问题。要解决这个问题,就要把A类对B类的控制权抽离出来,交给一个第三方去做,把控制权反转给第三方,就称作控制反转(IOC Inversion Of Control)。控制反转是一种思想,是能够解决问题的一种可能的结果,而依赖注入(Dependency Injection)就是其最典型的实现方法。
下面进行演示:
手机接口:
public interface Phone {
// 看新闻
void readNews();
// 玩游戏
void playGame();
// 拍照片
void takePhoto();
}
华为手机:
public class Huawei implements Phone {
@Override
public void readNews() {
System.out.println("用华为手机看新闻");
}
@Override
public void playGame() {
System.out.println("用华为手机玩游戏");
}
@Override
public void takePhoto() {
System.out.println("用华为手机拍照片");
}
}
苹果手机:
public class Apple implements Phone {
@Override
public void readNews() {
System.out.println("用苹果手机看新闻");
}
@Override
public void playGame() {
System.out.println("用苹果手机玩游戏");
}
@Override
public void takePhoto() {
System.out.println("用苹果手机拍照片");
}
}
小明直接控制手机:
public class XiaoMing {
Phone phone = new Huawei();
public void usePhone(){
phone.readNews();
phone.playGame();
phone.takePhoto();
}
}
测试:
public class Test {
public static void main(String[] args) {
XiaoMing xiaoMing = new XiaoMing();
xiaoMing.usePhone();
}
}
从这里可以看出,小明是直接控制了一台华为手机,当小明换手机时,我们得对小明进行改造,很不方便,这个时候我们就需要进行控制反转了,不要让小明去控制一台实实在在的手机。依赖注入是实现控制反转的手段,总共有三种注入方式:
1. 构造函数注入
public class XiaoMing {
Phone phone;
public XiaoMing(Phone phone){
this.phone = phone;
}
public void usePhone(){
phone.readNews();
phone.playGame();
phone.takePhoto();
}
}
public class Test {
public static void main(String[] args) {
XiaoMing xiaoMing = new XiaoMing(new Huawei());
xiaoMing.usePhone();
}
}
2. setter 函数注入
public class XiaoMing {
Phone phone;
public void setPhone(Phone phone) {
this.phone = phone;
}
public void usePhone(){
phone.readNews();
phone.playGame();
phone.takePhoto();
}
}
public class Test {
public static void main(String[] args) {
XiaoMing xiaoMing = new XiaoMing();
xiaoMing.setPhone(new Huawei());
xiaoMing.usePhone();
}
}
3. 方法参数注入
public class XiaoMing {
public void usePhone(Phone phone){
phone.readNews();
phone.playGame();
phone.takePhoto();
}
}
public class Test {
public static void main(String[] args) {
XiaoMing xiaoMing = new XiaoMing();
xiaoMing.usePhone(new Huawei());
}
}
上述三种方式进行依赖注入后都实现了控制反转,小明不再直接控制具体的手机,因此,小明换手机也不需要再对小明进行改造了,我们在 Test 类中就可以轻易的完成换手机。