解释器模式
解释器模式的英文是Interpreter Design Pattern。解释器模式为某个语言定义它的语法表示,并定义一个解释器来处理这个语法。
假如定义了一个新的加减乘除计算”语言“,语法规则如下:
- 运算符只包含加、减、乘、除,并且没有优先级的概念
- 表达式中,先书写数字,后书写运算符,空格隔开
- 按照先后顺序,取出两个数字和一个运算符计算结果,结果重新放入数字的最头部位置,循环上述过程,直到只剩下一个数字,这个数字就是表达式最终的计算结果。
举个例子来解释上面的语法规则。比如”8 3 2 4 - + *“这样一个表达式,按照上面的语法规则来处理,取出数字”8 3“和”-“运算法,计算得到5,于是表达式就变成了”5 2 4 + *“。然后,再取出数字”5 2“和”+“运算符,计算得到7,表达式就变成了”7 4 “。最后,取出数字”7 4“和”“运算符,最终得到的结果就是28。代码实现如下:
@interface DMDemoApplication : NSObject
@end
@implementation DMDemoApplication
- (void)test
{
[self interpret:@"8 3 2 4 - + *"];
}
- (void)interpret:(NSString *)expression
{
NSArray *tmpArray = [expression componentsSeparatedByString:@" "];
NSMutableArray *numberArray = [[NSMutableArray alloc] init];
NSMutableArray *operatorArray = [[NSMutableArray alloc] init];
NSInteger count = [tmpArray count];
for (NSInteger i = 0; i < count; i++) {
NSInteger j = count / 2 + 1;
NSString *str = [tmpArray objectAtIndex:i];
if (i < j) {
[numberArray addObject:str];
} else {
[operatorArray addObject:str];
}
}
for (NSInteger i = 0; i < [operatorArray count]; i++) {
NSString *operatorStr = [operatorArray objectAtIndex:i];
NSString *numStrOne = [numberArray objectAtIndex:0];
NSString *numStrTwo = [numberArray objectAtIndex:1];
[numberArray removeObjectAtIndex:1];
[numberArray removeObjectAtIndex:0];
NSInteger result = 0;
if ([operatorStr isEqualToString:@"+"]) {
result = [numStrOne integerValue] + [numStrTwo integerValue];
} else if ([operatorStr isEqualToString:@"-"]) {
result = [numStrOne integerValue] - [numStrTwo integerValue];
} else if ([operatorStr isEqualToString:@"*"]) {
result = [numStrOne integerValue] * [numStrTwo integerValue];
} else if ([operatorStr isEqualToString:@"/"]) {
result = [numStrOne integerValue] / [numStrTwo integerValue];
}
NSString *resultStr = [NSString stringWithFormat:@"%@", [NSNumber numberWithInteger:result]];
[numberArray insertObject:resultStr atIndex:0];
}
NSString *numStrOne = [numberArray objectAtIndex:0];
NSLog(@"%@结果为:%@", expression, numStrOne);
}
@end
在上面的代码实现中,语法规则的解析逻辑都集中在一个函数中,对于简单的语法规则的解析,这样的设计就足够了。但是,对于复杂的语法规则的解析,逻辑复杂,代码量多,所有的解析逻辑都耦合在一个函数中,这样显然是不合理的。这个时候,就要考虑拆分代码,将解析逻辑拆分到独立的小类中。
前面定义的语法规则有两类表达式,一类是数字,一类是运算符,运算符又包括加减乘除。利用解释器模式,可以把解析的工作拆分到DMZNumberExpression、DMZAdditionExpression、DMZSubstractionExpression、DMZMultiplicationExpression、DMZDivisionExpression这样五个解析类中。重构之后代码如下:
@protocol DMZExpression <NSObject>
- (NSInteger)interpret;
@end
@interface DMZNumberExpression : NSObject <DMZExpression>
- (instancetype)initWithString:(NSString *)str;
- (instancetype)initWithInter:(NSInteger)value;
@end
@interface DMZNumberExpression ()
@property (nonatomic, assign) NSInteger mValue;
@end
@implementation DMZNumberExpression
- (instancetype)initWithString:(NSString *)str
{
if (self = [super init]) {
self.mValue = [str integerValue];
}
return self;
}
- (instancetype)initWithInter:(NSInteger)value
{
if (self = [super init]) {
self.mValue = value;
}
return self;
}
- (NSInteger)interpret
{
return self.mValue;
}
@end
@interface DMZAdditionExpression : NSObject <DMZExpression>
- (instancetype)initWithNumberOne:(DMZNumberExpression *)numberOne numberTwo:(DMZNumberExpression *)numberTwo;
@end
@interface DMZAdditionExpression ()
@property (nonatomic, strong) DMZNumberExpression *mNumberOne;
@property (nonatomic, strong) DMZNumberExpression *mNumberTwo;
@end
@implementation DMZAdditionExpression
- (instancetype)initWithNumberOne:(DMZNumberExpression *)numberOne numberTwo:(DMZNumberExpression *)numberTwo
{
if (self = [super init]) {
self.mNumberOne = numberOne;
self.mNumberTwo = numberTwo;
}
return self;
}
- (NSInteger)interpret
{
return [self.mNumberOne interpret] + [self.mNumberTwo interpret];
}
@end
@interface DMZSubstractionExpression : NSObject <DMZExpression>
- (instancetype)initWithNumberOne:(DMZNumberExpression *)numberOne numberTwo:(DMZNumberExpression *)numberTwo;
@end
@interface DMZSubstractionExpression ()
@property (nonatomic, strong) DMZNumberExpression *mNumberOne;
@property (nonatomic, strong) DMZNumberExpression *mNumberTwo;
@end
@implementation DMZSubstractionExpression
- (instancetype)initWithNumberOne:(DMZNumberExpression *)numberOne numberTwo:(DMZNumberExpression *)numberTwo
{
if (self = [super init]) {
self.mNumberOne = numberOne;
self.mNumberTwo = numberTwo;
}
return self;
}
- (NSInteger)interpret
{
return [self.mNumberOne interpret] - [self.mNumberTwo interpret];
}
@end
@interface DMZMultiplicationExpression : NSObject <DMZExpression>
- (instancetype)initWithNumberOne:(DMZNumberExpression *)numberOne numberTwo:(DMZNumberExpression *)numberTwo;
@end
@interface DMZMultiplicationExpression ()
@property (nonatomic, strong) DMZNumberExpression *mNumberOne;
@property (nonatomic, strong) DMZNumberExpression *mNumberTwo;
@end
@implementation DMZMultiplicationExpression
- (instancetype)initWithNumberOne:(DMZNumberExpression *)numberOne numberTwo:(DMZNumberExpression *)numberTwo
{
if (self = [super init]) {
self.mNumberOne = numberOne;
self.mNumberTwo = numberTwo;
}
return self;
}
- (NSInteger)interpret
{
return [self.mNumberOne interpret] * [self.mNumberTwo interpret];
}
@end
@interface DMZDivisionExpression : NSObject <DMZExpression>
- (instancetype)initWithNumberOne:(DMZNumberExpression *)numberOne numberTwo:(DMZNumberExpression *)numberTwo;
@end
@interface DMZDivisionExpression ()
@property (nonatomic, strong) DMZNumberExpression *mNumberOne;
@property (nonatomic, strong) DMZNumberExpression *mNumberTwo;
@end
@implementation DMZDivisionExpression
- (instancetype)initWithNumberOne:(DMZNumberExpression *)numberOne numberTwo:(DMZNumberExpression *)numberTwo
{
if (self = [super init]) {
self.mNumberOne = numberOne;
self.mNumberTwo = numberTwo;
}
return self;
}
- (NSInteger)interpret
{
return [self.mNumberOne interpret] / [self.mNumberTwo interpret];
}
@end
@implementation DMDemoApplication
- (void)test
{
[self interpret:@"8 3 2 4 - + *"];
}
- (void)interpret:(NSString *)expression
{
NSArray *tmpArray = [expression componentsSeparatedByString:@" "];
NSMutableArray *numberArray = [[NSMutableArray alloc] init];
NSMutableArray *operatorArray = [[NSMutableArray alloc] init];
NSInteger count = [tmpArray count];
for (NSInteger i = 0; i < count; i++) {
NSInteger j = count / 2 + 1;
NSString *str = [tmpArray objectAtIndex:i];
if (i < j) {
[numberArray addObject:[[DMZNumberExpression alloc] initWithString:str]];
} else {
[operatorArray addObject:str];
}
}
for (NSInteger i = 0; i < [operatorArray count]; i++) {
NSString *operatorStr = [operatorArray objectAtIndex:i];
DMZNumberExpression *numOne = [numberArray objectAtIndex:0];
DMZNumberExpression *numTwo = [numberArray objectAtIndex:1];
[numberArray removeObjectAtIndex:1];
[numberArray removeObjectAtIndex:0];
id<DMZExpression> expression = nil;
if ([operatorStr isEqualToString:@"+"]) {
expression = [[DMZAdditionExpression alloc] initWithNumberOne:numOne numberTwo:numTwo];
} else if ([operatorStr isEqualToString:@"-"]) {
expression = [[DMZSubstractionExpression alloc] initWithNumberOne:numOne numberTwo:numTwo];
} else if ([operatorStr isEqualToString:@"*"]) {
expression = [[DMZMultiplicationExpression alloc] initWithNumberOne:numOne numberTwo:numTwo];
} else if ([operatorStr isEqualToString:@"/"]) {
expression = [[DMZDivisionExpression alloc] initWithNumberOne:numOne numberTwo:numTwo];
}
NSInteger result = [expression interpret];
DMZNumberExpression *tmpNumberExpression = [[DMZNumberExpression alloc] initWithInter:result];
[numberArray insertObject:tmpNumberExpression atIndex:0];
}
DMZNumberExpression *numberExpresionOne = [numberArray objectAtIndex:0];
NSLog(@"%@结果为:%@", expression, [NSNumber numberWithInteger:[numberExpresionOne interpret]]);
}
@end
网友评论