2010-02-10 37 views
12

Tôi cần phát triển một mô hình chiến lược mà tôi có một lớp học chính với ba lớp khác, nơi tôi cần tham chiếu đến các đối tượng của ba lớp khác bằng cách sử dụng đối tượng lớp chính.Để giải quyết đây là mô hình chiến lược sẽ giúp tôi? Nếu vậy xin vui lòng cho tôi cú pháp trong Objective-C?Làm thế nào để tạo ra một mô hình chiến lược trong Objective-C?

+0

này dường như là một bản sao của câu hỏi hiện tại của bạn: http://stackoverflow.com/questions/2229026 –

+0

Có, nhưng tôi đã không được đề cập bất cứ điều gì về mô hình chiến lược trong câu hỏi trước đây của tôi – Cathy

Trả lời

39

Bạn sẽ muốn xem xét cơ chế protocol của Objective-C. Dưới đây là một giao thức đơn giản với một phương pháp cần thiết duy nhất:

@protocol Strategy <NSObject> 

@required 
- (void) execute; 

@end 

Sau đó, bạn khai báo một lớp mà đáp rằng giao thức:

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

Việc thực hiện phải cung cấp phương pháp -execute (vì nó đã được khai báo là @required):

@implementation ConcreteStrategyA 

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

@end 

Bạn có thể tạo lớp tương tự ConcreteStrategyB nhưng tôi sẽ không hiển thị ở đây.

Cuối cùng, hãy tạo một lớp ngữ cảnh với thuộc tính duy trì chiến lược hiện tại.

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

- (void) execute; 

@end 

Đây là triển khai. Phương thức giao cho phương thức -execute của chiến lược chỉ xảy ra để được gọi là -truy cập là tốt, nhưng nó không phải là.

@implementation Context 

@synthesize strategy; 

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

@end 

Bây giờ tôi sẽ thực hiện một vài trường hợp và đưa vào sử dụng:

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

Giao diện điều khiển đầu ra cho thấy rằng chiến lược này đã được thay đổi thành công:

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 

Lưu ý rằng nếu giao thức không chỉ định @required, phương pháp là tùy chọn. Trong trường hợp này, ngữ cảnh cần kiểm tra xem chiến lược có triển khai phương pháp hay không:

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

Đây là mẫu Cocoa phổ biến được gọi là delegation. Để biết thêm thông tin về phái đoàn và các mẫu thiết kế khác trong ca cao, see this.

+0

Cảm ơn u rất nhiều cho các trả lời, một trong những nghi ngờ gì là 'setStrategy' từ khóa ở đây đại diện trong các trường hợp u đã thực hiện. – Cathy

+0

Phương thức '-setStrategy:' được tạo tự động bởi chỉ thị '@ synthesize'. Nếu thuộc tính được khai báo là 'retain', nó sẽ xử lý việc giữ lại/giải phóng (nhưng bạn vẫn phải giải phóng nó trong' -dealloc'). Nhưng nếu thuộc tính được khai báo là 'assign', nó thực hiện một phép gán đơn giản như một tham chiếu yếu, với giả định rằng cá thể được gán được bảo đảm tồn tại và được quản lý ở nơi khác. Trong trường hợp đó, nó không nên được phát hành. … Trong thực tế, tôi sẽ thay đổi câu trả lời của tôi cho hình thức thứ hai này. –

+0

Cảm ơn bạn đã trả lờ[email protected] nên tôi cần phải khai báo nó trong tập tin riêng biệt – Cathy

1

Đây là ví dụ cụ thể hơn một chút. Bạn có thể đặt từng mục trong một tệp riêng biệt. Tôi đã đặt tất cả trong một tệp để dễ hiểu.

// 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; 
} 
Các vấn đề liên quan