Objective-C - Шаблон методов шаблонов?

Итак, я читал о шаблонных методах в Objective-C и пытаюсь понять, что в них такого особенного. Насколько я понимаю, любой метод в базовом классе может быть переопределен, и супер может быть вызван? Так является ли метод шаблона чем-то большим, чем переопределение метода в базовом классе?

Если я ошибаюсь, не могли бы вы объяснить, что такое шаблон-метод-шаблон, и можете ли вы привести пример?

3 ответа

Решение

Да, шаблон шаблона немного больше, чем просто переопределение метода в базовом классе.

Шаблон шаблона может использоваться, когда схема алгоритма определена конкретно, однако шаги алгоритма остаются абстрактными. Это означает, что шаги могут быть реализованы по-разному. Но общая схема алгоритма не должна меняться.

Пример, который я только что создал на лету:

class Life {

   public method goThroughTheDay(){
     goToWork();
     eatLunch();
     comeBackHome();
     programABitMore();
   }
   abstract method goToWork();
   abstract method eatLunch();
   abstract method comeBackHome();
   abstract method programABitMore();
}

class GoodLife extends Life {
   //override all the abstract methods here
}

//The client application
Life life = new GoodLife();
life.goThroughTheDay();

По сути, то, как должен проходить день, конкретно определено в классе Life. Однако, детали процесса заботятся подклассом (то есть. GoodLife). Класс GoodLife будет реализовывать шаги совершенно иначе, чем возможный класс ToughLife.

Есть несколько вариаций этого паттерна; например, некоторые из шагов также могут быть конкретно определены. В этом примере eatLunch() может быть конкретно определен в классе Life; Это означает, что подклассы не должны изменять это поведение.

Шаблон имеет большой смысл, если у вас есть относительно сложный алгоритм, который может быть реализован различными способами.

======================================

Я как-то пропустил часть с Objective-C в моем ответе. Вот как это будет выглядеть в Objective-C:

@interface Life : NSObject

- (void) goThroughTheDay;

- (void) goToWork; // Abstract
- (void) eatLunch; // Abstract
- (void) comeBackHome; // Abstract
- (void) programABitMore; // Abstract

@end

@implementation Life

- (void) goThroughTheDay {

    [self goToWork];
    [self eatLunch];
    [self comeBackHome];
    [self programABitMore];
}

- (void) goToWork { [self doesNotRecognizeSelector:_cmd]; }
- (void) eatLunch { [self doesNotRecognizeSelector:_cmd]; }
- (void) comeBackHome { [self doesNotRecognizeSelector:_cmd]; }
- (void) programABitMore { [self doesNotRecognizeSelector:_cmd]; }

@end

@interface GoodLife : Life

@end

@implementation GoodLife

- (void) goToWork { NSLog(@"Good Work"); }
- (void) eatLunch { NSLog(@"Good Lunch"); }
- (void) comeBackHome { NSLog(@"Good Comeback"); }
- (void) programABitMore { NSLog(@"Good Programming"); }

@end

Objective-C не имеет встроенной поддержки абстрактных классов, поэтому я обошел его, используя doesNotRecognizeSelector: метод. Гораздо больше подробностей об абстрактных классах и Objective-C можно найти здесь.

Я подумал, что должен дать более конкретный ответ на Objective-C. Вы можете прочитать о методе шаблона, который используется в Какао на страницах Шаблонов дизайна какао яблок. Примером этого является drawRect: шаблонный метод. Как и другие методы шаблона, вы никогда не вызываете методы шаблона непосредственно самостоятельно. Это называется setNeedsDisplay, Смысл этого состоит в том, чтобы позволить каркасу оптимизировать чертеж. Если вы позвонили drawRect: непосредственно вы можете сделать ненужные перерисовки много раз.

На самом деле вам, вероятно, следует попытаться сделать каждый метод, который вы хотите переопределить в подклассе, шаблоном. Это уменьшает проблему знания того, следует ли вам вызывать реализацию базового класса при переопределении, и облегчает отладку. Вы можете просто поместить точку останова в базовый класс вместо всех переопределенных методов в подклассах.

Насколько я понимаю, любой метод в базовом классе может быть переопределен, и супер может быть вызван? Так является ли метод шаблона чем-то большим, чем переопределение метода в базовом классе?

Да, это гораздо больше, чем просто переопределение метода базового класса. Шаблонные методы - это способ реализации алгоритма, в котором некоторые шаги зависят от подкласса. Например, рассмотрим метод в Base, который имеет три основных шага: f1, f2 и f3. Каждый шаг содержит ряд утверждений. Здесь f1 и f3 одинаковы во всех подклассах, но f2 зависит от подкласса. Так что же здесь делать? Вы можете переопределить весь метод в операторах копирования подклассов f1 и f3, но это пустая трата. Таким образом, вы предоставляете только f2 в подклассе. Таким образом, вы определяете алгоритм (выполняете f1, затем выполняете f2, затем выполняете f3) в базовом классе, но предоставляете переопределенные хуки для подклассов (f2). Обратите внимание, что шаблонный метод в базовом классе является окончательным, поэтому подкласс не может изменить алгоритм, например, он не может изменить порядок f1, f2 и f3, ни один из подклассов не может пропустить шаги f1, f3.

Короче говоря, шаблон Template Methods не просто переопределяет, а использует наследование для обработки определенных ситуаций. Это не специфично для Obj-C, и я не могу предоставить вам ничего конкретного для Obj-C. Чтобы получить общее представление об этом шаблоне, я рекомендую следующее:

  1. Книга "Дизайны моделей" от GoF
  2. Head First Design Patterns
  3. Статья в Википедии о шаблонном методе

И есть также множество учебников / статей в Интернете. Основная идея не зависит от Obj-C.

Другие вопросы по тегам