美文网首页
设计模式之责任链

设计模式之责任链

作者: ParkinWu | 来源:发表于2015-09-16 19:04 被阅读24次

需求:有这样一个数组

NSArray * srcArr = @[@{@"name":@"张三",@"age":@18,@"sex":@"男"},
                         @"王五, 18, 男",
                         @[@"李四", @20, @"男"]];```
取出里面每个item,封装一个Person对象,属性如下:

import <Foundation/Foundation.h>

@interface Person : NSObject
@property (nonatomic, copy) NSString * name;
@property (nonatomic, assign) NSInteger age;
@property (nonatomic, copy) NSString * sex;
@end

##so easy !!!
#方法一:

import <Foundation/Foundation.h>

import "Person.h"

int main(int argc, const char * argv[]) {
NSArray * srcArr = @[@{@"name":@"张三",@"age":@18,@"sex":@"男"},
@"王五, 18, 男",
@[@"李四", @20, @"男"]];
NSMutableArray * desArr = [NSMutableArray arrayWithCapacity:1];
for (id item in srcArr) {
Person * per = [[Person alloc] init];
if ([item isKindOfClass:[NSDictionary class]]) {
//字典类型
NSDictionary * dict = (NSDictionary *)item;
per.name = [dict objectForKey:@"name"];
per.age = [[dict objectForKey:@"age"] integerValue];
per.sex = [dict objectForKey:@"sex"];
} else if ([item isKindOfClass:[NSString class]]) {
//字符串类型
NSString * str = (NSString *)item;
//以“,”分割
NSArray * coms = [str componentsSeparatedByString:@","];
per.name = coms[0];
per.age = [coms[1] integerValue];
per.sex = coms[2];
} else if ([item isKindOfClass:[NSArray class]]){
//数组类型
NSArray * arr = (NSArray *)item;
per.name = arr[0];
per.age = [arr[1] integerValue];
per.sex = arr[2];
} else {
NSLog(@"暂时没有这种情况");
}
[desArr addObject:per];
}
NSLog(@"desArr = %@", desArr);
return 0;
}

运行结果

desArr = (
"name = \U5f20\U4e09, age = 18, sex = \U7537",
"name = \U738b\U4e94, age = 18, sex = \U7537",
"name = \U674e\U56db, age = 20, sex = \U7537"
)

能完成需求!(这个最重要)

但是,有一天,需求改了!又加了一种不同类型

Person * person = [[Person alloc] init];
person.name = @"Jack";
person.age = 33;
person.sex = @"男";
NSArray * srcArr = @[@{@"name":@"张三",@"age":@18,@"sex":@"男"},
@"王五, 18, 男",
@[@"李四", @20, @"男",
person]];


问题不大,再改改条件语句,加一句else if即可
.....有一天又加了一种不同类型....
.....有一天又加一种不同.....
.....有一天又加.....
........
....
###变成这样了,直到你来接手代码了...

if () {
} else if () {

    } else if () {
      
    }  else if () {
      
    }  else if () {
      
    }  else if () {
      
    } 
    .......
    else {
    }

#what the fuck!!!
#根本不想看有木有!!!

#方法二:
###Handler.h

import <Foundation/Foundation.h>

@class Person;
@interface Handler : NSObject

  • (BOOL)canProcess:(id)item;
  • (Person *)converToObject:(id)item;
  • (void)processWithItem:(id)item
    container:(NSMutableArray *)container;
  • (void)setNextHandler:(Handler *)nextHandler;
    @end
###Handler.m

import "Handler.h"

import "Person.h"

@interface Handler ()
@property (nonatomic, strong) Handler * nextHandler;
@end
@implementation Handler

  • (void)setNextHandler:(Handler *)nextHandler {
    _nextHandler = nextHandler;
    }
  • (BOOL)canProcess:(id)item {
    return NO;
    }
  • (void)processWithItem:(id)item
    container:(NSMutableArray *)container {
    //能处理当前item
    if ([self canProcess:item]) {
    Person * person = [self converToObject:item];
    [container addObject:person];
    } else {
    //不能处理,传递给下一个
    if (self.nextHandler == nil) {
    NSLog(@"没有能够处理的processor了");
    } else {
    [self.nextHandler processWithItem:item container:container];
    }
    }
    }
    //专门用来供子类重写
  • (Person *)converToObject:(id)item {
    return nil;
    }
    @end
Handler类是抽象类,只用来继承,每个子类有个nextHandler属性,能够指向下一个责任者(类似单向链表)
```- (Person *)converToObject:(id)item```
子类重写该方法,来解析item,返回一个Person对象
```- (void)processWithItem:(id)item container:(NSMutableArray *)container```
如果能处理,就添加到数组中,否则就传递给下一个责任者
```- (BOOL)canProcess:(id)item```
判断当前责任者能不能处理(解析)该item

---
###ArrayProcessor.h

import "Handler.h"

@interface ArrayProcessor : Handler
@end

###ArrayProcessor.m

import "ArrayProcessor.h"

import "Person.h"

@implementation ArrayProcessor

  • (BOOL)canProcess:(id)item {
    return [item isKindOfClass:[NSArray class]];
    }
  • (Person *)converToObject:(id)item {
    Person * person = [[Person alloc] init];
    person.name = item[0];
    person.age = [item[1] integerValue];
    person.sex = item[2];
    return person;
    }
    @end
重写了父类的两个方法,实现自己不同的地方
###StringProcessor.h

import "Handler.h"

@interface StringProcessor : Handler
@end


###StringProcessor.m

import "StringProcessor.h"

import "Person.h"

@implementation StringProcessor

  • (BOOL)canProcess:(id)item {
    return [item isKindOfClass:[NSString class]];
    }
  • (Person *)converToObject:(id)item {
    Person * person = [[Person alloc] init];
    //字符串类型
    NSString * str = (NSString *)item;
    //以“,”分割
    NSArray * coms = [str componentsSeparatedByString:@","];
    person.name = coms[0];
    person.age = [coms[1] integerValue];
    person.sex = coms[2];
    return person;
    }
    @end

---
#这里是main
###main.m

import <Foundation/Foundation.h>

import "Person.h"

import "ArrayProcessor.h"

import "ObjectProcessor.h"

import "StringProcessor.h"

import "DictionaryProcessor.h"

import "Handler.h"

int main(int argc, const char * argv[]) {

Person * person = [[Person alloc] init];
person.name = @"Jack";
person.age = 33;
person.sex = @"男";
NSArray * srcArr = @[@{@"name":@"张三",@"age":@18,@"sex":@"男"},
                     @"王五, 18, 男",
                     @[@"李四", @20, @"男"],
                       person];
NSMutableArray * desArr = [NSMutableArray arrayWithCapacity:1];

//初始化各种Processor
ArrayProcessor * arrProcessor = [[ArrayProcessor alloc] init];
ObjectProcessor * objProcessor = [[ObjectProcessor alloc] init];
StringProcessor * strProcessor = [[StringProcessor alloc] init];
DictionaryProcessor * dictProcessor = [[DictionaryProcessor alloc] init];

//连接Processor,把几个处理的对象连接起来
[arrProcessor setNextHandler:objProcessor];
[objProcessor setNextHandler:strProcessor];
[strProcessor setNextHandler:dictProcessor];

//第一个开始处理
for (id item in srcArr) {
    [arrProcessor processWithItem:item container:desArr];
}


NSLog(@"desArr = %@", desArr);
return 0;

}

1. 创建各种Processor
2. 连接起来
3. 开始处理

> #分析
##第二种方法:
###缺点:
    1. 逻辑较第一种复杂
    2. 要提前创建所有情况的Processor对象
    3. 对于每个对象,都要遍历整个责任链,效率较低
###优点:
    1. 耦合较低,易于以后扩展
    2. 代码可读性高,有益身心健康!

#完毕!!!老规矩, [代码在这里](https://github.com/ParkinWu/OC002)

相关文章

网友评论

      本文标题:设计模式之责任链

      本文链接:https://www.haomeiwen.com/subject/cxlbcttx.html