2009-08-26 43 views

回答

11

不,Objective-C類別不是訪客模式的實現。在設計模式世界中,類別實際上並不完全匹配,因爲在大多數語言中將方法注入到沒有子類的現有類中是不可能的。我想說它更接近decorator pattern,但是這種模式通常是通過合成來實現的,即通過包裝要「增強」的對象實例。

訪問者模式對於封裝可應用於各種對象,結構等的算法邏輯非常有用。例如,如果要爲對象圖形創建HTML輸出,可以(A)編寫(B)使用訪問者模式並創建一個知道如何爲其訪問的每個節點生成HTML輸出的具體訪問者。

前一種方法更通用,任務T的邏輯分散在X,Y和Z類的小塊中。後一種方法將所有相關代碼放在單個訪問者對象中,這往往會簡化維護和防止「我忘了一堂課......」的問題。然而,對於簡單的情況來說,訪問者模式可以說有些過分 - 當它有幾個不同的並行功能並且希望從正在執行功能的類中抽象邏輯時,它確實值得回報。例如,您可以實現其他訪問者,這些訪問者可以產生PDF或RTF輸出等。每個訪問者可以按照必要的順序來處理遞歸併調用其自己的訪問方法,並且單獨的訪問者可以使用完全不同的順序。

應該指出,在許多語言中,訪問者模式使用方法重載(相同名稱,不同簽名/參數)。由於Objective-C不允許重載方法,因此您必須使用不同的方法名稱,但這實際上可以幫助避免因不知道哪個重載被調用而導致的錯誤。

2

類別可用於實現訪問者模式。

@protocol Visit 
- (void)acceptVisitor:(MyVisitor *)visitor; 
@end 

@interface Foo (Visit) <Visit> 
@end 

@interface Bar (Visit) <Visit> 
@end 

@implementation MyVisitor 

- (void)visit:(id)someObject { 
    if ([someObject conformsToProtocol:@protocol(Visit)]) { 
     [(id<Visit>)someObject acceptVisitor:self]; 
    } 
} 

- (void)visitFoo:(Foo *)foo { ... } 

- (void)visitBar:(Bar *)bar { ... } 

@end 

@implementation Foo (Visit) 
- (void)acceptVisitor:(MyVisitor *)visitor { 
    [visitor visitFoo:self]; 
} 
@end 

@implementation Bar (Visit) 
- (void)acceptVisitor:(MyVisitor *)visitor { 
    [visitor visitBar:Self]; 
} 
@end 

這是IMO比經典的GoF Visitor設計更簡潔,因爲沒有被訪問類的公共接口的污染,整個事情可以在訪問者類的編譯單元進行封裝。