メインクラスオブジェクトを使用して他の3つのクラスのオブジェクトを参照する必要がある他の3つのクラスを持つメインクラスがある戦略パターンを開発する必要があります.これを解決するには、戦略パターンが役立ちますか? もしそうなら、Objective-C の構文を教えてください。
2 に答える
Objective-C のプロトコルメカニズムを確認する必要があります。必要なメソッドが 1 つだけの単純なプロトコルを次に示します。
@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と呼ばれる一般的な Cocoa パターンです。Cocoa の委任およびその他の設計パターンの詳細については、こちらを参照してください。
もう少し具体的な例を示します。各項目を個別のファイルに入れることができます。わかりやすくするために、すべてを 1 つのファイルにまとめました。
// 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;
}