定義:高層模塊不應(yīng)該依賴低層模塊兑牡,二者都應(yīng)該依賴其抽象练对;抽象不應(yīng)該依賴細節(jié)遍蟋;細節(jié)應(yīng)該依賴抽象。
問題由來:類A直接依賴類B螟凭,假如要將類A改為依賴類C虚青,則必須通過修改類A的代碼來達成。這種場景下螺男,類A一般是高層模塊棒厘,負責復雜的業(yè)務(wù)邏輯;類B和類C是低層模塊烟号,負責基本的原子操作绊谭;假如修改類A,會給程序帶來不必要的風險汪拥。
解決方案:將類A修改為依賴接口I,類B和類C各自實現(xiàn)接口I篙耗,類A通過接口I間接與類B或者類C發(fā)生聯(lián)系迫筑,則會大大降低修改類A的幾率。
以上內(nèi)容來源于這里 宗弯。
再來說一下幾個概念:接口脯燃,抽象基類。
在java中蒙保,類(Class)辕棚、接口(Interface)、實現(xiàn)類(Implement)分別是三個東西。
在OC中類(Class)由.h文件(Interface)和.m文件(Implement)組成逝嚎。
所以O(shè)C中的Interface并不是java中的Interface扁瓢。真正java中的接口對應(yīng)于OC中的協(xié)議(Procotol)。
OC中的并沒有提供直接創(chuàng)建抽象基類的方式补君,一般都是通過在協(xié)議中定義方法屬性等引几,再由一個類去遵守該協(xié)議的方式得到抽象基類⊥焯或者你不實現(xiàn)協(xié)議伟桅,直接定義一個類,規(guī)定幾個方法叽掘,在實現(xiàn)文件里寫這幾個空方法楣铁,也可以把它當做抽象基類。
何時使用抽象基類何時使用接口關(guān)鍵還是取決于待繼承之間的聯(lián)系更扁。側(cè)重于它們之間的個性差異還是共性聯(lián)系民褂。
當個性大于共性。差異較大的個性間具有某些相同的行為疯潭,相同行為的實現(xiàn)方式有較大的區(qū)別赊堪,使用接口。
當共性大于個性竖哩,共性相同的個體間必然具備相同的屬性與行為哭廉,相同行為的實現(xiàn)方式具有一定區(qū)別,使用抽象基類相叁。
總結(jié)如下:
當在差異較大的對象間尋求功能上的共性時遵绰,使用接口。
當在共性較多的對象間尋求功能上的差異時增淹,使用抽象基類椿访。
下面進入正題。
需求虑润,有一個VIP學員成玫,比如我,想要學習設(shè)計模式的課程拳喻,于是我就依賴于這個課程哭当,但是學完之后,我又想學機器學習的課程冗澈,我還得依賴于機器學習的課程钦勘,如果我想學習其他的比如安全攻防的課程,還得繼續(xù)依賴亚亲,但是我學完這些后彻采,我還想學其他的腐缤,因為我的心里只有學習,學習使我快樂肛响。不過岭粤,打游戲也很快樂。我還得改動我自己的方法终惑,怎么樣不改動我自己绍在,就能學習很多的課程呢?
這時雹有,我學習了依賴倒置原則偿渡,我應(yīng)該學以致用,那么說來就來霸奕。
依賴倒置說的是不依賴其他的類溜宽,只依賴接口(抽象類不依賴實現(xiàn)類,實現(xiàn)類依賴抽象類)质帅,就是OC中的協(xié)議适揉,那么我就創(chuàng)建一個協(xié)議,協(xié)議里有一個方法叫學習煤惩。
#ifndef StudyProtocol_h
#define StudyProtocol_h
@protocol StudyProtocol
- (NSString *)study;
@end
#endif /* StudyProtocol_h */
我通過協(xié)議來獲取不同的課程
#import <Foundation/Foundation.h>
#import "StudyProtocol.h"
@interface VIPStudent : NSObject
- (void)studyCourse:(id<StudyProtocol>?)course;
@end
再定義一個DesignPattern類嫉嘀,遵守StudyProtocol。
#import <Foundation/Foundation.h>
#import "StudyProtocol.h"
@interface DesignPattern : NSObject<StudyProtocol>
@end
#import "DesignPattern.h"
@implementation DesignPattern
- (NSString *)study
{
????return @"學習設(shè)計模式知識";
}
@end
James老師的口頭禪魄揉,這里有一個點(要是Hank老師剪侮,就是,解釋一波):就是參數(shù)id<StudyProtocol>.
那么id<StudyProtocol>和id有什么區(qū)別呢洛退?
普通id指針能指向任何對象瓣俯,帶協(xié)議的id只能指向遵從協(xié)議的類的對象。
這樣就可以將遵守該協(xié)議的課程類傳給我了兵怯。
調(diào)用:
VIPStudent *vip = [[VIPStudent alloc] init];
[vip studyCourse:[DesignPattern new]];
[vip studyCourse:[CoreML new]];
[vip studyCourse:[Safety new]];
打印結(jié)果:
s = 學習設(shè)計模式知識
s = 學習機器學習知識
s = 學習安全攻防班知識
一個很簡單的Demo彩匕,但是用到了面向協(xié)議編程。這里多說一點媒区,使用繼承中的多態(tài)驼仪,也能實現(xiàn)該需求,但是驻仅,到底該需求使用什么方式去寫谅畅,判斷的依據(jù)還是個性大于共性還是共性大于個性。
大功告成噪服,打完收工,奉上Demo