Как создать шаблон стратегии в Objective-C? - PullRequest
12 голосов
/ 10 февраля 2010

Мне нужно разработать шаблон стратегии, в котором у меня есть основной класс с тремя другими классами, где мне нужно ссылаться на объекты трех других классов, используя объект основного класса. Чтобы решить эту проблему, шаблон стратегии мне поможет?Если да, пожалуйста, дайте мне синтаксис в Objective-C?

Ответы [ 2 ]

39 голосов
/ 10 февраля 2010

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

@protocol Strategy <NSObject>

@required
- (void) execute;

@end

Затем вы объявляете класс, который выполняет этот протокол:

@interface ConcreteStrategyA : NSObject <Strategy>
{
    // ivars for A
}
@end

Реализация должна предоставлять метод -execute (поскольку он был объявлен как @required):

@implementation ConcreteStrategyA

- (void) execute
{
    NSLog(@"Called ConcreteStrategyA execute method");
}

@end

Вы можете создать аналогичный ConcreteStrategyB класс, но я не собираюсь его здесь показывать.

Наконец, создайте контекстный класс со свойством, поддерживающим текущую стратегию.

@interface Context : NSObject
{
    id<Strategy> strategy;
}
@property (assign) id<Strategy> strategy;

- (void) execute;

@end

Вот реализация. Метод, который делегирует методу -execute стратегии, также называется -execute, но это не обязательно.

@implementation Context

@synthesize strategy;

- (void) execute
{
    [strategy execute];
}

@end

Теперь я сделаю несколько экземпляров и задействую их:

ConcreteStrategyA * concreteStrategyA = [[[ConcreteStrategyA alloc] init] autorelease];
ConcreteStrategyB * concreteStrategyB = [[[ConcreteStrategyB alloc] init] autorelease];
Context * context = [[[Context alloc] init] autorelease];

[context setStrategy:concreteStrategyA];
[context execute];
[context setStrategy:concreteStrategyB];
[context execute];    

Вывод консоли показывает, что стратегия была успешно изменена:

2010-02-09 19:32:56.582 Strategy[375:a0f] Called ConcreteStrategyA execute method
2010-02-09 19:32:56.584 Strategy[375:a0f] Called ConcreteStrategyB execute method

Обратите внимание, что если в протоколе не указано @required, метод является необязательным. В этом случае контекст должен проверить, реализует ли стратегия метод:

- (void) execute
{
    if ([strategy respondsToSelector:@selector(execute)])
        [strategy execute];
}

Это обычный шаблон Какао, называемый Delegation . Для получения дополнительной информации о делегировании и других шаблонах проектирования в Какао, см. Это .

1 голос
/ 09 июля 2014

Вот еще несколько конкретных примеров. Вы можете поместить каждый элемент в отдельный файл. Я поместил все это в один файл для простоты понимания.

//  main.m
//  StrategyWikipediaExample
//
//  Created by steve on 2014-07-08.
//  Copyright (c) 2014 steve. All rights reserved.
//

#import <Foundation/Foundation.h>

/**
 Equivalent to Java Interface
 All concrete Strategies conform to this protocol
 */
@protocol MathOperationsStrategy<NSObject>
- (void)performAlgorithmWithFirstNumber:(NSInteger)first secondNumber:(NSInteger)second;
@end

/**
 Concrete Strategies. 
 Java would say they "Extend" the interface.
 */

@interface AddStrategy : NSObject<MathOperationsStrategy>
@end
@implementation AddStrategy
- (void)performAlgorithmWithFirstNumber:(NSInteger)first secondNumber:(NSInteger)second
{
    NSInteger result = first + second;
    NSLog(@"Adding firstNumber: %ld with secondNumber: %ld yields : %ld", first, second, result);
}
@end

@interface SubtractStrategy : NSObject<MathOperationsStrategy>
@end
@implementation SubtractStrategy
- (void)performAlgorithmWithFirstNumber:(NSInteger)first secondNumber:(NSInteger)second
{
    NSInteger result = first - second;
    NSLog(@"Subtracting firstNumer: %ld with secondNumber: %ld yields: %ld", first, second, result);
}
@end

@interface MultiplyStrategy : NSObject<MathOperationsStrategy>
@end
@implementation MultiplyStrategy
- (void)performAlgorithmWithFirstNumber:(NSInteger)first secondNumber:(NSInteger)second
{
    NSInteger result = first * second;
    NSLog(@"Multiplying firstNumber: %ld with secondNumber: %ld yields: %ld", first, second, result);
}
@end

@interface Context : NSObject
@property (weak, nonatomic)id<MathOperationsStrategy>strategy; // reference to concrete strategy via protocol
- (id)initWithMathOperationStrategy:(id<MathOperationsStrategy>)strategy; // setter
- (void)executeWithFirstNumber:(NSInteger)first secondNumber:(NSInteger)second;
@end
@implementation Context
- (id)initWithMathOperationStrategy:(id<MathOperationsStrategy>)strategy
{
    if (self = [super init]) {
        _strategy = strategy;
    }
    return self;
}
- (void)executeWithFirstNumber:(NSInteger)first secondNumber:(NSInteger)second
{
    [self.strategy performAlgorithmWithFirstNumber:first secondNumber:second];
}
@end


int main(int argc, const char * argv[])
{

    @autoreleasepool {
        id<MathOperationsStrategy>addStrategy = [AddStrategy new];
        Context *contextWithAdd = [[Context alloc] initWithMathOperationStrategy:addStrategy];
        [contextWithAdd executeWithFirstNumber:10 secondNumber:10];

    }
    return 0;
}
...