Категории Objective-C == шаблон посетителя?

Можно ли сказать, что категории Objective-C являются реализацией шаблона проектирования посетителей?


person Jeff    schedule 26.08.2009    source источник


Ответы (2)


Нет, категории Objective-C не являются реализацией шаблона посетителя. Категории на самом деле не имеют точного соответствия в мире шаблонов проектирования, поскольку техника внедрения методов в существующие классы без подклассов невозможна в большинстве языков. Я бы сказал, что он ближе к шаблону декоратора, но этот шаблон обычно реализуется с помощью композиции, т.е. обернув экземпляр объекта, который вы хотите «улучшить».

Шаблон посетителя полезен для инкапсуляции логики алгоритма, который может быть применен к различным объектам, структурам и т. д. Например, если вы хотите создать вывод HTML для графа объектов, вы можете (A) написать метод htmlString для каждого object и вызывать его для каждого объекта, или (B) использовать шаблон посетителя и создать конкретного посетителя, который знает, как создавать выходные данные HTML для каждого посещаемого им узла.

Первый подход является более общим, а логика задачи T разбросана небольшими порциями по классам X, Y и Z. Второй подход помещает весь связанный код в один объект-посетитель, что, как правило, упрощает обслуживание и предотвращает «я». забыл, что один класс..." проблема. Тем не менее, шаблон посетителя, возможно, несколько неудобен для простых ситуаций — он действительно окупается, когда у вас есть несколько разных параллельных функций и вы хотите абстрагировать логику от классов, в которых выполняются функции. Например, вы можете реализовать других посетителей, которые выводят PDF или RTF и т. д. Каждый посетитель может позаботиться о рекурсии и вызывать свои собственные методы посещения в необходимом порядке, а отдельные посетители могут использовать совершенно другой порядок.

Следует отметить, что во многих языках шаблон посетителя использует перегрузку методов (одно и то же имя, разные сигнатуры/аргументы). Поскольку Objective-C не допускает перегрузку методов, вы должны использовать разные имена методов, но на самом деле это может помочь избежать ошибок, вызванных незнанием того, какая перегрузка вызывается.

person Quinn Taylor    schedule 26.08.2009

Категории можно использовать для реализации шаблона посетителя.

@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, поскольку нет загрязнения общедоступных интерфейсов посещаемых классов, и все это может быть инкапсулировано в модуле компиляции класса посетителя.

person Neil Gall    schedule 28.02.2011