iOS原生觀(guān)察者模式&重新設(shè)計(jì)觀(guān)察者模式

? ? ? ?原生KVO的實(shí)現(xiàn)依賴(lài)于強(qiáng)大的runtime運(yùn)行時(shí)機(jī)制冷尉,實(shí)現(xiàn)原理大致為:當(dāng)觀(guān)察某對(duì)象A的屬性時(shí)允耿,會(huì)動(dòng)態(tài)的創(chuàng)建這個(gè)類(lèi)的子類(lèi),并為這個(gè)新的子類(lèi)重寫(xiě)了Setter方法,在這個(gè)Setter方法里面負(fù)責(zé)通知觀(guān)察者屬性變化的情況距潘。

? ? ? ?前段時(shí)間面試的時(shí)候,面試官問(wèn)我只搁,如果不用系統(tǒng)的KVO模式音比,自己來(lái)實(shí)現(xiàn)一種設(shè)計(jì)模式,當(dāng)時(shí)可能由于緊張氢惋,一下子沒(méi)反應(yīng)過(guò)來(lái)洞翩,最后結(jié)果可想而知,現(xiàn)在想來(lái)明肮,對(duì)比現(xiàn)在所在的外包公司的種種不公平待遇菱农,總結(jié)下來(lái)一句話(huà),肚子里沒(méi)貨還真不行柿估。

? ? ? 閑話(huà)不多扯循未,先來(lái)簡(jiǎn)單說(shuō)一下如何自己實(shí)現(xiàn)NSNotificationCenter通知模式,然后秫舌,細(xì)聊如何通過(guò)協(xié)議實(shí)現(xiàn)KVO的妖,不同于原生KVO的實(shí)現(xiàn)方案。

? ? ? 通知中心實(shí)現(xiàn)方案足陨,首先進(jìn)行角色劃分嫂粟,一個(gè)單例類(lèi)A+抽象協(xié)議接口(包含接收到通知后實(shí)現(xiàn)的接口和發(fā)出通知的接口)Protocol+具體的實(shí)現(xiàn)類(lèi)B;

? ? ? ??客戶(hù)端: ? ?A ? 包含屬性數(shù)組 ?墨缘,B遵循Protocol星虹,實(shí)現(xiàn)協(xié)議方法,A數(shù)組持有B對(duì)象镊讼,當(dāng)A發(fā)出通知時(shí)宽涌,取出數(shù)組中的B對(duì)象,通過(guò)運(yùn)行時(shí)蝶棋,讓B實(shí)現(xiàn)協(xié)議方法卸亮,從而達(dá)到通知的目的。

這里玩裙,我們重點(diǎn)看一下KVO的實(shí)現(xiàn)方案兼贸,首先進(jìn)行角色劃分:

第一步 : 抽象出接口:所有觀(guān)察者必須遵循這個(gè)協(xié)議

// 抽象觀(guān)察者Observer

@protocol Observer

- (void)update:(Observable *)o msg:(NSObject *)msg;

@end

第二步:定義一個(gè)基類(lèi)Observable,所有被觀(guān)察者對(duì)象都必須繼承于Observable基類(lèi)

// 注冊(cè)觀(guān)察者- (void)addObserver:(id)o; ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?
// 刪除觀(guān)察者- (void)deleteObserver:(id)o;

// 刪除所有觀(guān)察者
- (void)deleteObservers;

// 觀(guān)察者數(shù)量
- (NSInteger)countObserver;

// 通知
- (void)notifyObservers;

- (void)notifyObservers:(NSObject *)msg;

// 更新數(shù)據(jù)
- (void)setChanged;

// 取消更新
- (void)clearChanged;

// 獲取更新?tīng)顟B(tài)
- (BOOL)hasChanged;

Observable.m文件實(shí)現(xiàn):

#import "Observable.h"@interface Observable()
@property (nonatomic,strong) NSMutableArray *obsArray;
@property (nonatomic,assign) BOOL changed;
@end

// 被觀(guān)察者
@implementation Observable
- (instancetype)init{?
? ? ? ?if (self = [super init]) {? ?
? ? ?_obsArray = [NSMutableArray array];? ? ? ?
?_changed = NO;? ? }?
? return self;}

// 注冊(cè)觀(guān)察者
- (void)addObserver:(id)o {? ? [_obsArray addObject:o];}
// 刪除觀(guān)察者
- (void)deleteObserver:(id)o {? ? [_obsArray removeObject:o];}
// 刪除所有觀(guān)察者
- (void)deleteObservers {? ? [_obsArray removeAllObjects];}
// 觀(guān)察者數(shù)量
- (NSInteger)countObserver?{? ? return _obsArray.count;}
- (void)notifyObservers {? ? [self notifyObservers:nil];}
- (void)notifyObservers:(NSObject *)msg
{? ?
? ? if (!_changed)?{? ? ? ? return ;? ? }? ?
? ? [self clearChanged];? ?
? ? ?for (idobj in _obsArray) {
[obj update:self msg:msg];
}
}

// 更新數(shù)據(jù)
- (void)setChanged {
_changed = YES;
}

// 取消更新
- (void)clearChanged {
_changed = NO吃溅;
}

// 獲取更新?tīng)顟B(tài)
- (BOOL)hasChanged {
return _changed;
}

客戶(hù)端實(shí)現(xiàn):

WXObservable *observable = [WXObservable new];

[observable addObserver:[CoffeeObserver new]];

[observable addObserver:[SimpleObserver new]];

[observable setTitle:@"思維的切換"];

[observable push];

[observable push];

[observable push];

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末溶诞,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子决侈,更是在濱河造成了極大的恐慌很澄,老刑警劉巖,帶你破解...
    沈念sama閱讀 210,978評(píng)論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異甩苛,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)俏站,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 89,954評(píng)論 2 384
  • 文/潘曉璐 我一進(jìn)店門(mén)讯蒲,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人肄扎,你說(shuō)我怎么就攤上這事墨林。” “怎么了犯祠?”我有些...
    開(kāi)封第一講書(shū)人閱讀 156,623評(píng)論 0 345
  • 文/不壞的土叔 我叫張陵旭等,是天一觀(guān)的道長(zhǎng)。 經(jīng)常有香客問(wèn)我衡载,道長(zhǎng)搔耕,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 56,324評(píng)論 1 282
  • 正文 為了忘掉前任痰娱,我火速辦了婚禮弃榨,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘梨睁。我一直安慰自己鲸睛,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,390評(píng)論 5 384
  • 文/花漫 我一把揭開(kāi)白布坡贺。 她就那樣靜靜地躺著官辈,像睡著了一般。 火紅的嫁衣襯著肌膚如雪遍坟。 梳的紋絲不亂的頭發(fā)上拳亿,一...
    開(kāi)封第一講書(shū)人閱讀 49,741評(píng)論 1 289
  • 那天,我揣著相機(jī)與錄音政鼠,去河邊找鬼风瘦。 笑死,一個(gè)胖子當(dāng)著我的面吹牛公般,可吹牛的內(nèi)容都是我干的万搔。 我是一名探鬼主播,決...
    沈念sama閱讀 38,892評(píng)論 3 405
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼官帘,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼瞬雹!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起刽虹,我...
    開(kāi)封第一講書(shū)人閱讀 37,655評(píng)論 0 266
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤酗捌,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體胖缤,經(jīng)...
    沈念sama閱讀 44,104評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡尚镰,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,451評(píng)論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了哪廓。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片狗唉。...
    茶點(diǎn)故事閱讀 38,569評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖涡真,靈堂內(nèi)的尸體忽然破棺而出分俯,到底是詐尸還是另有隱情,我是刑警寧澤哆料,帶...
    沈念sama閱讀 34,254評(píng)論 4 328
  • 正文 年R本政府宣布缸剪,位于F島的核電站,受9級(jí)特大地震影響东亦,放射性物質(zhì)發(fā)生泄漏杏节。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,834評(píng)論 3 312
  • 文/蒙蒙 一讥此、第九天 我趴在偏房一處隱蔽的房頂上張望拢锹。 院中可真熱鬧,春花似錦萄喳、人聲如沸卒稳。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,725評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)充坑。三九已至,卻和暖如春染突,著一層夾襖步出監(jiān)牢的瞬間捻爷,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,950評(píng)論 1 264
  • 我被黑心中介騙來(lái)泰國(guó)打工份企, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留也榄,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 46,260評(píng)論 2 360
  • 正文 我出身青樓司志,卻偏偏與公主長(zhǎng)得像甜紫,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子骂远,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,446評(píng)論 2 348

推薦閱讀更多精彩內(nèi)容