軟件開發(fā)六大設(shè)計(jì)原則 合稱SOLID
依賴倒置原則也是其中一個(gè)
依賴倒置原則定義:
- 上層模塊不應(yīng)該依賴底層模塊扩氢,它們都應(yīng)該依賴于抽象爷辱。
- 抽象不應(yīng)該依賴于細(xì)節(jié),細(xì)節(jié)應(yīng)該依賴于抽象双饥。
比較晦澀弟断,如同軟件行業(yè)中的哲學(xué)
其中上層模塊與下層模塊
- 業(yè)務(wù)層 邏輯層 數(shù)據(jù)層
業(yè)務(wù)層中的軟件真正要進(jìn)行的操作,就是做什么昏翰,或者叫面向用戶層
邏輯層是軟件現(xiàn)階段為了業(yè)務(wù)層的需求提供的實(shí)現(xiàn)細(xì)節(jié)刘急,也就是怎么做
數(shù)據(jù)層指業(yè)務(wù)層和邏輯層所需要的數(shù)據(jù)模型
什么是抽象和細(xì)節(jié)?
抽象如其名字一樣叔汁,是一件很抽象的事物。抽象往往是相對(duì)于具體而言的码邻,具體可以被稱為細(xì)節(jié)另假,當(dāng)然也可以被稱為具象。
比如 抽象可以是畫开睡,而國畫苟耻,油畫,素描就是具體
具體映射到軟件開發(fā)中凶杖,抽象可以是接口或者抽象類形式
public interface Driveable{
void drive();
}
class Bike implements Driveable{
@Override 注解 標(biāo)識(shí)子類對(duì)父類方法的重載,在沒有abstract
public void drive() {
// TODO Auto-generated method stub
System.out.println("Bike drive.");
}
}
class Car implements Driveable{
@Override
public void drive() {
// TODO Auto-generated method stub
System.out.println("Car drive.");
}
}
Driveable就是抽象腾么,然后 bike car 就是細(xì)節(jié)。
依賴倒置的好處
比如一個(gè)類person攘须,在傳統(tǒng)編碼中是要什么給什么殴泰,引入什么對(duì)象
要出門,則三種交通工具都引入捞魁,作為成員變量离咐。
這就是依賴于細(xì)節(jié)了,而且在交通方式變更中開銷會(huì)很大宵蛀。
public class Person {
// private Bike mBike;
// private Car mCar;
// private Train mTrain;
private Driveable mDriveable;
public Person() {
//mBike = new Bike();
//mCar = new Car();
//mTrain = new Train();
mDriveable = new Train();
}
public void chumen() {
System.out.println("出門了");
//mBike.drive();
//mCar.drive();
//mTrain.drive();
mDriveable.drive();
}
}
所以 倒置過來 加入一層抽象
讓人依賴于抽象术陶,改,只需要改抽象瞳别,引入只需要引入抽象 再實(shí)例化即可
抽象不應(yīng)該依賴細(xì)節(jié)杭攻,細(xì)節(jié)應(yīng)該依賴于抽象
什么是控制反轉(zhuǎn)
Inversion of Control
public class Person {
private Driveable mDriveable;
public Person(Driveable driveable) {
this.mDriveable = driveable;
}
public void chumen() {
System.out.println("出門了");
mDriveable.drive();
}
}
也就是說 不讓person創(chuàng)建對(duì)象 而是留一個(gè)接口兆解,讓外側(cè)創(chuàng)建實(shí)例并傳遞進(jìn)去
把內(nèi)部依賴的創(chuàng)建權(quán)力移交給外部,只關(guān)注依賴提供的功能锅睛,但并不關(guān)心依賴的創(chuàng)建
IoC離不開IoC的容器,也就是實(shí)例化抽象的地方
public class Restaurant {
public static void peican(int orderid,int flowid) {
WaimaiYuan person;
Food food;
if ( orderid == 0) {
food = new PijiuYa();
} else {
food = new DuojiaoYutou();
}
if ( flowid % 2 == 0 ) {
person = new Xiaohuozi(food);
} else {
person = new XiaoGuniang(food);
}
person.songWaiMai();
}
}
比如例子中的Restaurant就是一個(gè)Ioc容器
配置 一詞比較重要
Spring相關(guān)度比較高
IoC模式最核心的地方就是在依賴方與被依賴方之間辣垒,引入了第三方印蔬,這個(gè)第三方統(tǒng)稱為IoC容器,因?yàn)镮oC容器的介入例驹,導(dǎo)致上層模塊對(duì)于它的依賴的實(shí)例化控制權(quán)發(fā)生變化,也就是所謂的控制反轉(zhuǎn)的意思荤胁。
依賴注入 Dependency Injection
其實(shí)也是講我們移交出對(duì)于依賴實(shí)例化的控制權(quán)屎债,和IoC類似,并留有接口扔茅,在需要該依賴的時(shí)候注入進(jìn)去injection
- 實(shí)現(xiàn)依賴注入有三種方式:
1.構(gòu)造函數(shù)中注入
2.setter方式注入
3.接口注入
接口的存在召娜,表明了一種依賴配置的能力
在軟件框架中,讀取xml配置文件玖瘸,或者利用反射技術(shù)讀取注解,然后根據(jù)配置信息璃诀,框架動(dòng)態(tài)將一些依賴配置給特定的接口類蔑匣,我們也可以說injector也依賴于接口,而不是特定的實(shí)現(xiàn)類裁良,這樣進(jìn)一步提高了準(zhǔn)確性與靈活性
總結(jié)
- 依賴倒置是面向?qū)ο箝_發(fā)領(lǐng)域中的軟件設(shè)計(jì)原則价脾,它倡導(dǎo)上層模塊不依賴于底層模塊,抽象不依賴細(xì)節(jié)侨把。
- 依賴反轉(zhuǎn)是遵守依賴倒置這個(gè)原則而提出來的一種設(shè)計(jì)模式,它引入了 IoC 容器的概念获枝。
- 依賴注入是為了實(shí)現(xiàn)依賴反轉(zhuǎn)的一種手段之一骇笔。
- 它們的本質(zhì)是為了代碼更加的“高內(nèi)聚,低耦合”机隙。