訪問者模式
在訪問者模式(Visitor Pattern)中纺阔,我們使用了一個訪問者類,它改變了元素類的執(zhí)行算法。通過這種方式椒袍,元素的執(zhí)行算法可以隨著訪問者改變而改變。這種類型的設(shè)計模式屬于行為型模式吞获。根據(jù)模式羽嫡,元素對象已接受訪問者對象渤弛,這樣訪問者對象就可以處理元素對象上的操作。
介紹
意圖:主要將數(shù)據(jù)結(jié)構(gòu)與數(shù)據(jù)操作分離滤愕。
主要解決:穩(wěn)定的數(shù)據(jù)結(jié)構(gòu)和易變的操作耦合問題。
何時使用:需要對一個對象結(jié)構(gòu)中的對象進行很多不同的并且不相關(guān)的操作怜校,而需要避免讓這些操作"污染"這些對象的類间影,使用訪問者模式將這些封裝到類中。
如何解決:在被訪問的類里面加一個對外提供接待訪問者的接口茄茁。
關(guān)鍵代碼:在數(shù)據(jù)基礎(chǔ)類里面有一個方法接受訪問者魂贬,將自身引用傳入訪問者。
應用實例:您在朋友家做客裙顽,您是訪問者付燥,朋友接受您的訪問,您通過朋友的描述愈犹,然后對朋友的描述做出一個判斷键科,這就是訪問者模式。
優(yōu)點: 1漩怎、符合單一職責原則勋颖。 2、優(yōu)秀的擴展性勋锤。 3饭玲、靈活性。
缺點: 1叁执、具體元素對訪問者公布細節(jié)茄厘,違反了迪米特原則。 2谈宛、具體元素變更比較困難次哈。 3、違反了依賴倒置原則吆录,依賴了具體類亿乳,沒有依賴抽象。
使用場景: 1径筏、對象結(jié)構(gòu)中對象對應的類很少改變葛假,但經(jīng)常需要在此對象結(jié)構(gòu)上定義新的操作。 2滋恬、需要對一個對象結(jié)構(gòu)中的對象進行很多不同的并且不相關(guān)的操作聊训,而需要避免讓這些操作"污染"這些對象的類,也不希望在增加新操作時修改這些類恢氯。
注意事項:訪問者可以對功能進行統(tǒng)一带斑,可以做報表鼓寺、UI、攔截器與過濾器勋磕。
實現(xiàn)
我們將創(chuàng)建一個定義接受操作的 ComputerPart 接口妈候。Keyboard、Mouse挂滓、Monitor 和 Computer 是實現(xiàn)了 ComputerPart 接口的實體類苦银。我們將定義另一個接口 ComputerPartVisitor,它定義了訪問者類的操作赶站。Computer 使用實體訪問者來執(zhí)行相應的動作幔虏。
VisitorPatternDemo,我們的演示類使用 Computer贝椿、ComputerPartVisitor 類來演示訪問者模式的用法想括。
步驟 1
定義一個表示元素的接口。
@interface ComputerPart :NSObject <NSObject>
@property (nonatomic,strong)NSMutableArray *list;
- (void)accept:(id<ComputerPartVisitor>)com;
@end
步驟 2
創(chuàng)建擴展了上述類的實體類烙博。
@interface Mouse : ComputerPart
@end
@interface Computer : ComputerPart
@end
@implementation Mouse
- (void)accept:(id<ComputerPartVisitor>)com{
[com visitMouse:self];
}
@end
@implementation Computer
- (void)accept:(id<ComputerPartVisitor>)com{
for (ComputerPart *item in self.list) {
[item accept:com];
}
[com visit:self];
}
- (instancetype)init{
self =[super init];
self.list=[NSMutableArray array];
[self.list addObject:[Mouse new]];
return self;
}
@end
步驟 3
定義一個表示訪問者的接口瑟蜈。
@protocol ComputerPartVisitor <NSObject>
- (void)visit:(Computer *)pt;
- (void)visitMouse:(Mouse *)mou;
@end
步驟 4
創(chuàng)建實現(xiàn)了上述類的實體訪問者。
@interface ComputerDisplayVisitor : NSObject< ComputerPartVisitor>
- (void)visitMouse:(Mouse *)mou;
- (void)visit:(Computer *)pt;
@end
@implementation ComputerDisplayVisitor
- (void)visitMouse:(Mouse *)mou{
NSLog(@"display mouse");
}
- (void)visit:(Computer *)pt{
NSLog(@"display computer");
}
@end
步驟 5
使用 ComputerPartDisplayVisitor 來顯示 Computer 的組成部分渣窜。
ComputerPart *part=[Computer new];
[part accept:[ComputerDisplayVisitor new]];
步驟 6
執(zhí)行程序踪栋,輸出結(jié)果:
2019-05-23 11:14:36.133715+0800 test[2832:21862177] display mouse
2019-05-23 11:14:36.133827+0800 test[2832:21862177] display computer
參考資料
runoob