2010-02-10 10 views
12

Ich muss ein Strategie-Muster entwickeln, wo ich eine Hauptklasse mit anderen drei Klassen habe, wo ich auf die Objekte der anderen drei Klassen mit dem Haupt-Klasse-Objekt verweisen muss. Um das zu lösen, wird das Strategie-Muster mir helfen? Wenn ja, bitte geben Sie mir die Syntax in Objective-C?Wie erstellt man ein Strategie-Pattern in Objective-C?

+0

Dies scheint ein Duplikat Ihrer bestehende Frage zu sein: http://stackoverflow.com/questions/2229026 –

+0

Ja, aber ich habe nichts über Strategie-Muster in meiner vorherigen Frage erwähnt – Cathy

Antwort

39

Sie sollten sich Objective-C protocol Mechanismus ansehen. Hier ist ein einfaches Protokoll mit einem einzigen erforderlichen Verfahren:

@protocol Strategy <NSObject> 

@required 
- (void) execute; 

@end 

Dann erklären Sie eine Klasse, die dieses Protokoll erfüllt:

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

Die Implementierung muss bietet die -execute Methode (da es als @required erklärt wurde):

@implementation ConcreteStrategyA 

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

@end 

Sie können eine ähnliche ConcreteStrategyB Klasse machen, aber ich bin es hier nicht geht zu zeigen.

Schließlich erstellen Sie eine Kontextklasse mit einer Eigenschaft, die die aktuelle Strategie beibehält.

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

- (void) execute; 

@end 

Hier ist die Implementierung. Die Methode, die an die Methode -execute der Strategie delegiert, heißt zufällig auch -execute, aber das muss nicht sein.

@implementation Context 

@synthesize strategy; 

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

@end 

Jetzt werde ich ein paar Instanzen machen und setzen sie zu benutzen:

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];  

Die Konsole Ausgabe zeigt, dass die Strategie erfolgreich geändert wurde:

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 

Beachten Sie, dass, wenn die Protokoll gibt @required nicht an, die Methode ist optional. In diesem Fall muss der Kontext prüfen, ob die Strategie, um die Methode implementiert:

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

Dies ist ein gemeinsames Cocoa Muster delegation genannt. Weitere Informationen zur Delegierung und anderen Entwurfsmustern in Cocoa finden Sie unter see this.

+0

Thank u so viel für die Antwort, man bezweifle, was das 'setStrategy' Schlüsselwort hier in den von dir gemachten Fällen darstellt. – Cathy

+0

Die Methode '-setStrategy:' wird automatisch von der Anweisung '@ synthesize' generiert. Wenn die Eigenschaft 'retain' deklariert ist, wird sie beibehalten/freigeben (aber Sie müssen es immer noch in' -dealloc' freigeben). Wenn die Eigenschaft jedoch als "Zuweisung" deklariert ist, wird eine einfache Zuweisung als schwache Referenz durchgeführt, mit der Annahme, dass die zugewiesene Instanz garantiert existiert und an anderer Stelle verwaltet wird. In diesem Fall sollte es nicht freigegeben werden. ... In der Tat werde ich meine Antwort auf diese zweite Form ändern. –

+0

Danke für die Antwort.Das @ Protokoll sollte ich in separate Datei deklarieren müssen – Cathy

1

Hier ist ein bisschen konkreteres Beispiel. Sie können jedes Element in eine separate Datei einfügen. Ich habe alles in eine Datei geschrieben, um das Verständnis zu erleichtern.

// 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; 
}