Objective-C - Шаблон методов шаблонов? - PullRequest
7 голосов
/ 16 ноября 2011

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

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

Ответы [ 3 ]

23 голосов
/ 16 ноября 2011

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

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

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

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 можно найти здесь .

2 голосов
/ 16 июля 2012

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

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

1 голос
/ 16 ноября 2011

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

Да, это гораздо больше, чем просто переопределение метода базового класса.Шаблонные методы - это способ реализации алгоритма, в котором некоторые шаги зависят от подкласса.Например, рассмотрим метод в 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
  3. Статья в Википедии о шаблонном методе

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

...