views:

44

answers:

1

I understand the concept of the "strategy pattern" but i am still a little bit confused.

Let'say we have a class named Dog Dog has MovementBehaviour (interface) which can be MovementBehaviourNormal & MovementBehaviourFast MovementBehaviourNormal and MovementBehaviourFast both contain a method named move

QUESTION: what is the best way to access the dog attributes from the move method? Is it a bad idea to pass the dog object to MovementBehaviour as a delegate?

+3  A: 

Generally, you shouldn't be accessing properties on Dog directly from your strategy object. Instead, what you can do is provide a move method that returns a new position based on the old position. So, for example, if you have:

@interface Dog : NSObject {
    NSInteger position;
    DogStrategy * strategy;
}
@property(nonatomic, assign) NSInteger position;
@property(nonatomic, retain) DogStrategy * strategy;
- (void)updatePosition;
@end

@implementation Dog
@synthesize position, strategy;

- (void)updatePosition {
    self.position = [self.strategy getNewPositionFromPosition:self.position];
}
@end
@interface DogStrategy : NSObject { }
- (NSInteger)getNewPositionFromPosition:(NSInteger)pos;
@end

// some parts elided for brevity

@interface NormalDogStrategy : DogStrategy { }
@end

@implementation NormalDogStrategy
- (NSInteger)getNewPositionFromPosition:(NSInteger)pos {
    return pos + 2;
}
@end

Then, when you instantiate a Dog, you can assign it the NormalDogStrategy and call [dog updatePosition] - the Dog will ask its strategy for its updated position, and assign that to its instance variable itself. You've avoided exposing the internals of Dog to your DogStrategy and still accomplished what you intended.

Tim
thanks a lot, great details. NormalDogStrategy shouldn't inherit from DogStrategy but it should use it as an interface: NormalDogStrategy<DogStrategy>. Correct me if i am wrong
aryaxt
And DogStrategy should be a protocol, not an actual class?
aryaxt
If you're using the actual strategy pattern, then no - since NormalDogStrategy is *a kind of* DogStrategy, not an object that fills the contract of a DogStrategy and does other stuff too. If you made DogStrategy a protocol, it would follow to make NormalDogStrategy a protocol as well, and you can't do that since you have to implement methods in NormalDogStrategy. (This is where abstract classes would come in handy in ObjC, but we just have to live without.)
Tim
Also (random bonus thought): if you ever want common instance variables on the strategy itself, you need the parent strategy (in this case DogStrategy) to be an object, not a protocol.
Tim