2010-02-10 9 views
12

Ho bisogno di sviluppare un modello di strategia in cui ho una classe principale con altre tre classi in cui ho bisogno di fare riferimento agli oggetti delle altre tre classi usando l'oggetto di classe principale. Per risolvere questo è il modello di strategia mi aiuterà? Se sì, per favore dammi la sintassi in Objective-C?Come creare un modello di strategia in Objective-C?

+0

Questo sembra essere un duplicato della tua domanda esistente: http://stackoverflow.com/questions/2229026 –

+0

Sì, ma non ho detto nulla su modello di strategia nella precedente interrogazione – Cathy

risposta

39

Ti consigliamo di guardare il meccanismo protocol di Objective-C. Ecco un semplice protocollo con un unico metodo richiesto:

@protocol Strategy <NSObject> 

@required 
- (void) execute; 

@end 

Poi si dichiara una classe che soddisfa quel protocollo:

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

L'applicazione deve fornire il metodo -execute (da quando è stato dichiarato come @required):

@implementation ConcreteStrategyA 

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

@end 

è possibile effettuare una simile ConcreteStrategyB classe, ma io non ho intenzione di mostrare qui.

Infine, creare una classe di contesto con una proprietà che mantenga la strategia corrente.

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

- (void) execute; 

@end 

Ecco l'implementazione. Il metodo che delega al metodo -execute della strategia si chiama anche -execute, ma non deve essere.

@implementation Context 

@synthesize strategy; 

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

@end 

Ora farò alcuni casi e mettere loro di utilizzare:

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

La console mostra che la strategia è stata cambiata con successo:

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 

Nota che se il il protocollo non specifica @required, il metodo è facoltativo. In questo caso, il contesto ha bisogno di controllare se la strategia implementa il metodo:

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

Questo è un modello di cacao comune denominato delegation. Per ulteriori informazioni sulla delega e altri modelli di progettazione in Cocoa, see this.

+0

Thank u tanto per il rispondi, un dubbio su quale sia la parola chiave "setStrategy" qui rappresentata nelle istanze che hai creato. – Cathy

+0

Il metodo '-setStrategy:' viene generato automaticamente dalla direttiva '@ synthesize'. Se la proprietà è dichiarata 'retain', si occupa di conservare/rilasciare (ma devi ancora rilasciarlo in' -dealloc'). Ma se la proprietà è dichiarata 'assign', fa un semplice assegnamento come riferimento debole, con l'assunto che l'istanza assegnata sia garantita e che sia gestita altrove. In tal caso non dovrebbe essere rilasciato. ... In effetti, cambierò la mia risposta a questa seconda forma. –

+0

Grazie per la risposta.Il @protocol dovrebbe essere necessario dichiararlo in un file separato – Cathy

1

Ecco un esempio un po 'più concreto. Puoi mettere ogni elemento in un file separato. Ho messo tutto in un unico file per facilità di comprensione.

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