定義
High level modules should not depend upon low level modules,Both should depend upon abstractions.Abstractions should not depend upon details.Details should depend upon abstracts.
翻譯過來:
1.高層模塊不應(yīng)該依賴低層模塊妓布,兩者都應(yīng)該依賴抽象
2.抽象不應(yīng)該依賴細(xì)節(jié)
3.細(xì)節(jié)應(yīng)該依賴抽象
也可以說高層模塊崭歧,低層模塊,細(xì)節(jié)都應(yīng)該依賴抽象
每一個(gè)邏輯的實(shí)現(xiàn)都是由顆粒原子邏輯組成的扑馁,顆粒原子邏輯就是低層模塊,而顆粒原子邏輯組成的模塊就是高層模塊翅娶。在ios語言中弄屡,抽象就是協(xié)議,不能直接被實(shí)例化的搬设,細(xì)節(jié)就是實(shí)現(xiàn)類穴店,實(shí)現(xiàn)協(xié)議而產(chǎn)生的類就是細(xì)節(jié),可以直接被實(shí)例化拿穴。
具體表現(xiàn)
模塊間的依賴通過抽象發(fā)生迹鹅,實(shí)現(xiàn)類之間不發(fā)生直接的依賴關(guān)系,其依賴關(guān)系是協(xié)議產(chǎn)生的贞言。
協(xié)議不依賴實(shí)現(xiàn)類
實(shí)現(xiàn)類依賴協(xié)議
更加精簡的定義就是“面向接口編程”—OOD(Object-Oriented Design斜棚,面向?qū)ο笤O(shè)計(jì))的精髓之一。
優(yōu)點(diǎn)
采用依賴倒置原則可以減少類間的耦合性该窗,提高系統(tǒng)的穩(wěn)定弟蚀,降低并行開發(fā)引起的風(fēng)險(xiǎn),提高代碼的可讀性和可維護(hù)性酗失。
場景模擬
小明喜歡看文學(xué)作品
場景模擬UML 圖
簡單代碼
@interface LiteraryClassic : NSObject
-(void)read;
@end
@implementation LiteraryClassic
-(void)read{
? ? NSLog(@"讀文學(xué)經(jīng)典");
}
@end
#import "LiteraryClassic.h"
@interface XiaoMing : NSObject
-(void)read:(LiteraryClassic *)literaryClassic;
@end
@implementation XiaoMing
-(void)read:(LiteraryClassic *)literaryClassic
{
? ? [literaryClassic read];
}
@end
測試
LiteraryClassic * literary=[LiteraryClassic new];
? ? XiaoMing * xiaoming=[XiaoMing new];
? ? [xiaoming read:literary];
結(jié)果
2018-04-03 17:18:58.591721+0800 設(shè)計(jì)模式原則[77605:5784593] 讀文學(xué)經(jīng)典
這樣小明就能看文學(xué)經(jīng)典了义钉。目前來看,沒有啥問題规肴。
場景變更
小明突然想看小說了捶闸。
場景變更UML圖
場景變更代碼實(shí)現(xiàn)
@interface Novel : NSObject
-(void)read;
@end
@implementation Novel
-(void)read{
? ? NSLog(@"讀小說");
}
@end
修改小明類增加一個(gè)讀小說的功能
-(void)readnovel:(Novel*)novel;
-(void)readnovel:(Novel*)novel{
? ? [novel read];
}
測試
Novel * novel = [Novel new];
? ? [xiaoming readnovel:novel];
結(jié)果
2018-04-03 17:37:14.518287+0800 設(shè)計(jì)模式原則[82210:5805086] 讀小說
這樣小明就可以讀小說了。
雖然我們這樣修改可以實(shí)現(xiàn)小明讀小說拖刃,但是我們需要修改小明類删壮。那么每增加一個(gè)類別,那么都要重新修改小明類兑牡。
導(dǎo)致這樣的原因是因?yàn)?b>小明類與每種書籍都是強(qiáng)依賴央碟,緊耦合導(dǎo)致的。
具體分析
看小明類均函,此類是一個(gè)高層模塊亿虽,并且是一個(gè)細(xì)節(jié)實(shí)現(xiàn)類,此類依賴的是一個(gè)文學(xué)經(jīng)典LiteraryClassic類苞也,而文學(xué)經(jīng)典LiteraryClassic類也是一個(gè)細(xì)節(jié)實(shí)現(xiàn)類洛勉。這是不是就與我們說的依賴倒置原則相違背呢?依賴倒置原則是說我們的高層模塊如迟,實(shí)現(xiàn)類收毫,細(xì)節(jié)類都應(yīng)該是依賴與抽象,依賴與接口和抽象類。
代碼重構(gòu)UML圖?
代碼重構(gòu)
@protocol IRead<NSObject>
-(void)read;
@end
#import "IRead.h"
@interface LiteraryClassicNew : NSObject<IRead>
@end
@implementation LiteraryClassicNew
-(void)read{
? ? NSLog(@"讀文學(xué)經(jīng)典");
}
@end
#import "IRead.h"
@interface NovelNew : NSObject<IRead>
@end
#import "NovelNew.h"
@implementation NovelNew
-(void)read{
? ? NSLog(@"讀小說");
}
@end
#import "IRead.h"
@protocol IReader<NSObject>
-(void)read:(id<IRead>)iread;
@end
#import "IReader.h"
@interface XiaoMingNew : NSObject<IReader>
@end
#import "XiaoMingNew.h"
@implementation XiaoMingNew
-(void)read:(id<IRead>)iread{
? ? [iread read];
}
@end
測試
id<IReader>ireader=[XiaoMingNew new];
id<IReader> read = [NovelNew new];
? ? [ireader read:read];
? ? read=[LiteraryClassicNew new];
? ? [ireader read:read];
結(jié)果
2018-04-03 18:04:03.545562+0800 設(shè)計(jì)模式原則[89054:5835572] 讀小說
2018-04-03 18:04:03.545770+0800 設(shè)計(jì)模式原則[89054:5835572] 讀文學(xué)經(jīng)典
這樣設(shè)計(jì)我們發(fā)現(xiàn)牛哺,小明和文學(xué)經(jīng)典還是小說就沒有耦合和依賴關(guān)系陋气,依賴關(guān)系是靠協(xié)議之間。這就是依賴倒置原則引润,我們依賴的對象是一個(gè)協(xié)議巩趁,就可以適應(yīng)所有實(shí)現(xiàn)此協(xié)議的具體類的變化。
依賴的三種方法
依賴是可以傳遞淳附,A對象依賴B對象议慰,B又依賴C,C又依賴D奴曙,……别凹,依賴不止。只要做到抽象依賴洽糟,即使是多層的依賴傳遞也無所謂懼炉菲。?
構(gòu)造函數(shù)傳遞依賴對象
Setter方法傳遞依賴對象
接口聲明依賴
這上面三種依賴其實(shí)就是傳入的參數(shù)是個(gè)協(xié)議,而不是具體類而已坤溃。
依賴倒置原則的經(jīng)驗(yàn)
依賴倒置原則的本質(zhì)就是通過抽象(協(xié)議)使各個(gè)類或模塊的實(shí)現(xiàn)彼此獨(dú)立拍霜,不互相影響,實(shí)現(xiàn)模塊間的松耦合薪介。我們在項(xiàng)目中使用這個(gè)原則要遵循下面的規(guī)則:
每個(gè)類盡量都有協(xié)議類
任何類都不應(yīng)該從具體類派生
盡量不要覆寫基類的方法?
結(jié)合里氏替換原則使用?
依賴倒置原則是6個(gè)設(shè)計(jì)原則中最難以實(shí)現(xiàn)的原則祠饺,它是實(shí)現(xiàn)開閉原則的重要方法,在項(xiàng)目中汁政,大家只要記住是”面向接口編程”就基本上是抓住了依賴倒置原則的核心了道偷。
參考博客
下一篇博客
設(shè)計(jì)模式原則之接口隔離原則