Tôi đang cố gắng để xây dựng một FSM để kiểm soát một bộ đếm thời gian trong (iphone sdk) mục tiêu c. Tôi cảm thấy đó là một bước cần thiết, bởi vì tôi đã kết thúc bằng mã spaghetti khó chịu chứa các trang của câu lệnh if-then. Sự phức tạp, không dễ đọc và khó khăn trong việc thêm/thay đổi các tính năng dẫn tôi đến thử một giải pháp chính thức hơn như thế này.Làm thế nào để làm cho một máy nhà nước hữu hạn cơ bản trong mục tiêu-C
Trong ngữ cảnh của ứng dụng, trạng thái của bộ đếm thời gian xác định một số tương tác phức tạp với NSManagedObjects, Dữ liệu cốt lõi, v.v. Tôi đã bỏ tất cả chức năng đó ngay bây giờ, trong nỗ lực để có được một cái nhìn rõ ràng về mã FSM.
Vấn đề là, tôi không thể tìm thấy bất kỳ ví dụ nào về loại mã này trong Obj-C và tôi không tự tin về cách tôi đã dịch nó từ mã ví dụ C++ mà tôi đang sử dụng. (Tôi không biết C++ ở tất cả, vì vậy có một số đoán liên quan.) Tôi đang dựa trên phiên bản này của một thiết kế mô hình nhà nước về bài viết này: http://www.ai-junkie.com/architecture/state_driven/tut_state1.html. Tôi không làm một trò chơi, nhưng bài viết này phác thảo các khái niệm làm việc cho những gì tôi đang làm.
Để tạo mã (được đăng bên dưới), tôi phải học rất nhiều khái niệm mới, bao gồm giao thức obj-c, v.v. Bởi vì đây là những điều mới mẻ đối với tôi, cũng giống như mô hình thiết kế của nhà nước, tôi hy vọng một số ý kiến phản hồi về việc thực hiện này. Đây có phải là cách bạn làm việc với các đối tượng giao thức hiệu quả trong obj-c không?
Đây là giao thức:
@class Timer;
@protocol TimerState
-(void) enterTimerState:(Timer*)timer;
-(void) executeTimerState:(Timer*)timer;
-(void) exitTimerState:(Timer*)timer;
@end
Đây là đối tượng Timer (trong rút gọn nhất hình thức của nó) tập tin tiêu đề:
@interface Timer : NSObject
{
id<TimerState> currentTimerState;
NSTimer *secondTimer;
id <TimerViewDelegate> viewDelegate;
id<TimerState> setupState;
id<TimerState> runState;
id<TimerState> pauseState;
id<TimerState> resumeState;
id<TimerState> finishState;
}
@property (nonatomic, retain) id<TimerState> currentTimerState;
@property (nonatomic, retain) NSTimer *secondTimer;
@property (assign) id <TimerViewDelegate> viewDelegate;
@property (nonatomic, retain) id<TimerState> setupState;
@property (nonatomic, retain) id<TimerState> runState;
@property (nonatomic, retain) id<TimerState> pauseState;
@property (nonatomic, retain) id<TimerState> resumeState;
@property (nonatomic, retain) id<TimerState> finishState;
-(void)stopTimer;
-(void)changeState:(id<TimerState>) timerState;
-(void)executeState:(id<TimerState>) timerState;
-(void) setupTimer:(id<TimerState>) timerState;
Và việc thực hiện hẹn giờ Object:
#import "Timer.h"
#import "TimerState.h"
#import "Setup_TS.h"
#import "Run_TS.h"
#import "Pause_TS.h"
#import "Resume_TS.h"
#import "Finish_TS.h"
@implementation Timer
@synthesize currentTimerState;
@synthesize viewDelegate;
@synthesize secondTimer;
@synthesize setupState, runState, pauseState, resumeState, finishState;
-(id)init
{
if (self = [super init])
{
id<TimerState> s = [[Setup_TS alloc] init];
self.setupState = s;
//[s release];
id<TimerState> r = [[Run_TS alloc] init];
self.runState = r;
//[r release];
id<TimerState> p = [[Pause_TS alloc] init];
self.pauseState = p;
//[p release];
id<TimerState> rs = [[Resume_TS alloc] init];
self.resumeState = rs;
//[rs release];
id<TimerState> f = [[Finish_TS alloc] init];
self.finishState = f;
//[f release];
}
return self;
}
-(void)changeState:(id<TimerState>) newState{
if (newState != nil)
{
[self.currentTimerState exitTimerState:self];
self.currentTimerState = newState;
[self.currentTimerState enterTimerState:self];
[self executeState:self.currentTimerState];
}
}
-(void)executeState:(id<TimerState>) timerState
{
[self.currentTimerState executeTimerState:self];
}
-(void) setupTimer:(id<TimerState>) timerState
{
if ([timerState isKindOfClass:[Run_TS class]])
{
secondTimer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(currentTime) userInfo:nil repeats:YES];
}
else if ([timerState isKindOfClass:[Resume_TS class]])
{
secondTimer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(currentTime) userInfo:nil repeats:YES];
}
}
-(void) stopTimer
{
[secondTimer invalidate];
}
-(void)currentTime
{
//This is just to see it working. Not formatted properly or anything.
NSString *text = [NSString stringWithFormat:@"%@", [NSDate date]];
if (self.viewDelegate != NULL && [self.viewDelegate respondsToSelector:@selector(updateLabel:)])
{
[self.viewDelegate updateLabel:text];
}
}
//TODO: releases here
- (void)dealloc
{
[super dealloc];
}
@end
Đừng lo lắng rằng có những điều còn thiếu trong lớp học này. Nó không làm bất cứ điều gì thú vị được nêu ra. Tôi hiện chỉ đang đấu tranh với cú pháp chính xác. Hiện tại nó biên dịch (và hoạt động) nhưng phương thức isKindOfClass gọi các cảnh báo trình biên dịch gây ra (phương thức không được tìm thấy trong giao thức). Tôi không thực sự chắc chắn rằng tôi muốn sử dụng isKindOfClass anyway. Tôi đã nghĩ đến việc cho mỗi đối tượng id<TimerState>
một chuỗi tên và sử dụng chuỗi đó thay thế.
Lưu ý khác: tất cả các khai báo id<TimerState>
ban đầu là các khai báo TimerState *. Nó có vẻ hợp lý để giữ chúng như là tài sản. Không chắc chắn nếu nó có ý nghĩa với id<TimerState>
của.
Dưới đây là một ví dụ về một trong các lớp nhà nước:
#import "TimerState.h"
@interface Setup_TS : NSObject <TimerState>{
}
@end
#import "Setup_TS.h"
#import "Timer.h"
@implementation Setup_TS
-(void) enterTimerState:(Timer*)timer{
NSLog(@"SETUP: entering state");
}
-(void) executeTimerState:(Timer*)timer{
NSLog(@"SETUP: executing state");
}
-(void) exitTimerState:(Timer*)timer{
NSLog(@"SETUP: exiting state");
}
@end
Một lần nữa, cho đến nay nó không làm bất cứ điều gì ngoại trừ thông báo rằng những gì giai đoạn (hoặc tiểu bang) nó ở Nhưng đó không phải là. điểm.
Điều tôi hy vọng tìm hiểu ở đây là liệu kiến trúc này có được viết chính xác bằng ngôn ngữ obj-c hay không. Một vấn đề cụ thể mà tôi gặp phải là việc tạo ra các đối tượng id trong hàm init của timer. Như bạn có thể thấy, tôi đã nhận xét các bản phát hành, vì chúng đã gây ra cảnh báo "phát hành không tìm thấy trong giao thức". Tôi đã không chắc chắn làm thế nào để xử lý đó.
Điều tôi không cần là nhận xét về mã này quá mức hoặc không có nghĩa hình thức vô nghĩa hoặc bất kỳ điều gì. Nó đáng để tôi học điều này ngay cả khi những ý tưởng đó là sự thật. Nếu nó giúp, hãy nghĩ về nó như một thiết kế lý thuyết cho một FSM trong obj-c.
Cảm ơn bạn trước vì bất kỳ nhận xét hữu ích nào.
(điều này không giúp quá nhiều: Finite State Machine in Objective-C)
Bạn cũng có thể có một giao thức phù hợp với một giao thức khác để không cần phải đề cập đến cả hai lần - khai báo nó như '@protocol TimerState'. Điều này nói với trình biên dịch hơn tất cả các đối tượng TimerState cũng phải tuân theo giao thức NSObject. –
Chuck
Mà gần như chắc chắn những gì bạn muốn làm trong trường hợp này. Điểm tuyệt vời. – jlehr
Điều đó chắc chắn làm cho trình biên dịch trở nên hạnh phúc. – mwt