I need to develop a strategy pattern where i have a main class with other three classes where i need to refer to the objects of the other three classes using the main class object.To solve this is the strategy pattern will help me? If so please do give me the syntax in Objective-C?
-
This appears to be a duplicate of your existing question: http://stackoverflow.com/questions/2229026 – Rob Keniger Feb 10 '10 at 03:32
-
Yes but i have not mentioned anything about strategy pattern in my previous question – Cathy Feb 10 '10 at 03:40
2 Answers
You'll want to look at Objective-C's protocol mechanism. Here's a simple protocol with a single required method:
@protocol Strategy <NSObject>
@required
- (void) execute;
@end
Then you declare a class that fulfills that protocol:
@interface ConcreteStrategyA : NSObject <Strategy>
{
// ivars for A
}
@end
The implementation must provide the -execute
method (since it was declared as @required
):
@implementation ConcreteStrategyA
- (void) execute
{
NSLog(@"Called ConcreteStrategyA execute method");
}
@end
You can make a similar ConcreteStrategyB
class, but I'm not going to show it here.
Finally, make a context class with a property maintaining the current strategy.
@interface Context : NSObject
{
id<Strategy> strategy;
}
@property (assign) id<Strategy> strategy;
- (void) execute;
@end
Here is the implementation. The method that delegates to the strategy's -execute
method just happens to be called -execute as well, but it doesn't have to be.
@implementation Context
@synthesize strategy;
- (void) execute
{
[strategy execute];
}
@end
Now I'll make a few instances and put them to use:
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];
The console output shows that the strategy was successfully changed:
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
Note that if the protocol does not specify @required
, the method is optional. In this case, the context needs to check whether the strategy implements the method:
- (void) execute
{
if ([strategy respondsToSelector:@selector(execute)])
[strategy execute];
}
This is a common Cocoa pattern called delegation. For more information on delegation and other design patterns in Cocoa, see this.

- 20,545
- 2
- 64
- 95
-
Thank u so much for the reply,one doubt what is the 'setStrategy' keyword here represents in the instances u have made. – Cathy Feb 10 '10 at 03:54
-
The `-setStrategy:` method is automatically generated by the `@synthesize` directive. If the property is declared `retain`, it takes care of doing retain/release (but you still have to release it in `-dealloc`). But if the property is declared `assign`, it does a simple assignment as a weak reference, with the assumption that the the assigned instance is guaranteed to exist and be managed elsewhere. In that case it should not be released. …In fact, I am going to change my answer to this second form. – Jon Reid Feb 10 '10 at 04:01
-
Thanks for the reply. The @protocol should i need to declare it in seperate file – Cathy Feb 10 '10 at 04:39
-
1Generally you declare the @protocol in the same header that uses it. The strategy pattern is extremely common in Cocoa, though it's often referred to as Delegate. – Rob Napier Feb 10 '10 at 04:48
-
3Rather than id
, it is usually better to make Strategy itself inherit from the – Rob Napier Feb 10 '10 at 04:50protocol: "@protocol Strategy " This is almost always what you want, and simplifies usage. -
-
The question of what you declare whhere is a separate question which revolves around reducing unnecessary recompilation. But I would put the protocol in its own header. – Jon Reid Feb 10 '10 at 04:57
-
Rob, thanks for pointing out the bit on making the protocol inherit from another protocol. I'm going to change my answer to reflect that, thanks! – Jon Reid Feb 10 '10 at 05:01
-
Now i am getting with the output, I have declared the @protocol in ConcreteStrategyA.h and ConcreteStrategyB.h files so in the Context.m there is warning as: duplicate declaration for the protocol Strategy. how should i solve this problem? – Cathy Feb 10 '10 at 06:03
-
Cathy, you're getting "duplicate declaration" because, uh, you're declaring it twice. Put the protocol in a header file instead. – Jon Reid Feb 10 '10 at 06:07
Here's a bit more of a concrete example. You can put each item in a separate file. I've put it all in one file for ease of understanding.
// 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;
}

- 19,393
- 7
- 65
- 62