命令模式
命令模式的英文是Command Design Pattern。命令模式将请求(命令)封装为一个对象,这样可以使用不同的请求参数化其他对象(将不同请求依赖注入到其他对象),并且能够支持请求(命令)的排队执行、记录日志、撤销等(附加控制)功能。
命令模式用的最核心的实现手段,是将函数封装成对象。C语言支持函数指针,可以把函数当作变量传递来传递去。但是,在大部分编程语言中,函数没法作为参数传递给其他函数,也没法赋值给变量。借助命令模式,可以将函数封装成对象。具体来说就是,设计一个包含这个函数的类,实例化一个对象传来穿去,这样就可以实现把函数像对象一样使用。
当把函数封装成对象之后,对象就可以存储下来,方便控制执行。所以,命令模式的主要作用和应用场景,是用来控制命令的执行,比如,异步、延迟、排队执行命令、撤销重做命令、存储命令、给命令记录日志等等,这才是命令模式能发挥独一无二作用的地方。
命令模式的实战讲解
整个手游后端服务器轮询获取客户单发来的请求,获取到请求之后,借助命令模式,把请求包含的数据和处理逻辑封装为命令对象,并存储在内存队列中。然后,再从队列中取出一定数量的命令来执行。执行完成之后,再重新开始新的一轮轮询。示例代码如下:
@interface DMQueue<ObjectType> : NSObject
- (BOOL)isEmpty;
- (void)enqueue:(ObjectType)oneObject;
- (ObjectType)dequeue;
@end
@interface DMQueue ()
@property (nonatomic, strong) NSMutableArray *mArray;
@end
@implementation DMQueue
- (BOOL)isEmpty
{
NSInteger count = [self.mArray count];
BOOL isEmpty = NO;
if (count == 0) {
isEmpty = YES;
}
return isEmpty;
}
- (void)enqueue:(id)oneObject
{
[self.mArray addObject:oneObject];
}
- (id)dequeue
{
id oneObject = nil;
if ([self.mArray count] > 0) {
oneObject = [self.mArray objectAtIndex:0];
[self.mArray removeObjectAtIndex:0];
}
return oneObject;
}
- (NSMutableArray *)mArray
{
if (_mArray == nil) {
_mArray = [[NSMutableArray alloc] init];
}
return _mArray;
}
@end
@protocol DMCommand <NSObject>
- (void)execute;
@end
@interface DMGotDiamondCommand : NSObject <DMCommand>
- (instancetype)initWithData:(NSDictionary *)data;
@end
@implementation DMGotDiamondCommand
- (instancetype)initWithData:(NSDictionary *)data
{
if (self = [super init]) {
// 数据处理
}
return self;
}
- (void)execute
{
// 执行相应逻辑
}
@end
@interface DMGotStartCommand : NSObject <DMCommand>
- (instancetype)initWithData:(NSDictionary *)data;
@end
@implementation DMGotStartCommand
- (instancetype)initWithData:(NSDictionary *)data
{
if (self = [super init]) {
// 数据处理
}
return self;
}
- (void)execute
{
// 执行相应逻辑
}
@end
@interface DMHitObstacleCommand : NSObject <DMCommand>
- (instancetype)initWithData:(NSDictionary *)data;
@end
- (instancetype)initWithData:(NSDictionary *)data
{
if (self = [super init]) {
// 数据处理
}
return self;
}
- (void)execute
{
// 执行相应逻辑
}
@end
@interface DMArchiveCommand : NSObject <DMCommand>
- (instancetype)initWithData:(NSDictionary *)data;
@end
@implementation DMArchiveCommand
- (instancetype)initWithData:(NSDictionary *)data
{
if (self = [super init]) {
// 数据处理
}
return self;
}
- (void)execute
{
// 执行相应逻辑
}
@end
@interface DMGameApplication : NSObject
@end
@implementation DMGameApplication
- (void)mainLoop
{
NSInteger maxHandleCountPerLoop = 100;
DMQueue *queue = [[DMQueue alloc] init];
while (YES) {
NSMutableArray *requests = [[NSMutableArray alloc] init];
for (NSString *request in requests) {
NSMutableDictionary *data = [[NSMutableDictionary alloc] init];
id<DMCommand> commonad = nil;
if ([request isEqualToString:@"GOT_DIAMOND"]) {
commonad = [[DMGotDiamondCommand alloc] initWithData:data];
} else if([request isEqualToString:@"GOT_STAR"]){
commonad = [[DMGotStartCommand alloc] initWithData:data];
} else if([request isEqualToString:@"HIT_OBSTACLE"]){
commonad = [[DMHitObstacleCommand alloc] initWithData:data];
} else if([request isEqualToString:@"ARCHIVE"]){
commonad = [[DMArchiveCommand alloc] initWithData:data];
}
[queue enqueue:commonad];
}
NSInteger handledCount = 0;
while (handledCount < maxHandleCountPerLoop) {
if ([queue isEmpty]) {
break;
}
id<DMCommand> command = [queue dequeue];
[command execute];
}
}
}
@end
网友评论