过滤器模式
过滤器模式(Filter Pattern)或标准模式(Criteria Pattern)是一种设计模式,这种模式允许开发人员使用不同的标准来过滤一组对象,通过逻辑运算以解耦的方式把它们连接起来。这种类型的设计模式属于结构型模式,它结合多个标准来获得单一标准。
实现
我们将创建一个 Person 对象、Criteria 接口和实现了该接口的实体类,来过滤 Person 对象的列表。CriteriaPatternDemo,我们的演示类使用 Criteria 对象,基于各种标准和它们的结合来过滤 Person 对象的列表。
过滤器模式的 UML 图
创建一个类,在该类上应用标准。
@interface Person_2 : NSObject
@property (nonatomic,copy,readonly) NSString *name;
@property (nonatomic,copy,readonly) NSString *gender;
@property (nonatomic,copy,readonly) NSString *maritalStatus;
- (NSString *)getName;
- (NSString *)getGender;
- (NSString *)getMaritalStatus;
- (instancetype)initWithName:(NSString *)name gender:(NSString *)gender maritalStatus:(NSString *)maritalStatus;
@end
步骤 2
为标准(Criteria)创建一个接口。
@protocol Criteria <NSObject>
-(NSMutableArray<Person_2 *> *)meetCriteria:(NSMutableArray<Person_2 * > *)list;
@end
步骤 3
创建实现了 Criteria 接口的实体类。
@interface CriteriaMale : NSObject <Criteria>
- (NSMutableArray<Person_2 *> *)meetCriteria:(NSMutableArray<Person_2 *> *)list;
@end
@interface CriteriaSingle : NSObject <Criteria>
- (NSMutableArray<Person_2 *> *)meetCriteria:(NSMutableArray<Person_2 *> *)list;
@end
@implementation CriteriaMale
-(NSMutableArray *)meetCriteria:(NSMutableArray *)list{
NSMutableArray *newList=[NSMutableArray array];
for (Person_2 *item in list) {
if ([item.getGender.uppercaseString isEqualToString:@"MALE"]) {
[newList addObject:item];
}
}
return newList;
}
@end
@implementation CriteriaSingle
-(NSMutableArray *)meetCriteria:(NSMutableArray *)list{
NSMutableArray *newList=[NSMutableArray array];
for (Person_2 *item in list) {
if ([item.getMaritalStatus.lowercaseString isEqualToString:@"single"]) {
[newList addObject:item];
}
}
return newList;
}
@end
and 和or
@interface andCriteria : NSObject <Criteria>
@property (nonatomic,strong) id<Criteria> _Nullable criteria;
@property (nonatomic,strong) id<Criteria> _Nullable otherCriteria;
- (NSMutableArray<Person_2 *> *)meetCriteria:(NSMutableArray <Person_2 *>*)list;
@end
@interface orCriteria : NSObject <Criteria>
@property (nonatomic,strong) id<Criteria> _Nullable criteria;
@property (nonatomic,strong) id<Criteria> _Nullable otherCriteria;
- (NSMutableArray<Person_2 *> *)meetCriteria:(NSMutableArray <Person_2 *>*)list;
@end
@implementation andCriteria
- (NSMutableArray<Person_2 *> *)meetCriteria:(NSMutableArray <Person_2 *>*)list{
NSMutableArray<Person_2 *> *newList2=[NSMutableArray array];
[newList2 addObjectsFromArray:[self.criteria performSelector:@selector(meetCriteria:)
withObject:list]];
return [self.otherCriteria performSelector:@selector(meetCriteria:) withObject:newList2];
}
@end
@implementation orCriteria
- (NSMutableArray<Person_2 *> *)meetCriteria:(NSMutableArray <Person_2 *>*)list{
NSMutableArray<Person_2 *> *newList1=[NSMutableArray array];
NSMutableArray<Person_2 *> *newList2=[NSMutableArray array];
[newList2 addObjectsFromArray:[self.criteria performSelector:@selector(meetCriteria:)
withObject:list]];
[newList1 addObjectsFromArray:[self.criteria performSelector:@selector(meetCriteria:)
withObject:list]];
for (Person_2 *item in newList2) {
if ([newList1 containsObject:item] == NO) {
[newList1 addObject:item];
}
}
return newList1;
}
@end
步骤4
使用不同的标准(Criteria)和它们的结合来过滤 Person 对象的列表。
NSMutableArray *list1 =[NSMutableArray array];
[list1 addObject:[[Person_2 alloc]initWithName:@"Join" gender:@"Male" maritalStatus:@"single"]];
[list1 addObject:[[Person_2 alloc]initWithName:@"Bob" gender:@"Single" maritalStatus:@"single"]];
[list1 addObject:[[Person_2 alloc]initWithName:@"Mike" gender:@"Single" maritalStatus:@"Male"]];
CriteriaMale *male=[CriteriaMale new];
CriteriaSingle *signle=[CriteriaSingle new];
andCriteria *and=[andCriteria new];
orCriteria *or=[orCriteria new];
NSLog(@"Males:%@",[male meetCriteria:list1]);
NSLog(@"Single:%@",[signle meetCriteria:list1]);
and.criteria = male;
and.otherCriteria = signle;
NSLog(@"and:%@",[and meetCriteria:list1]);
or.criteria = male;
or.otherCriteria = signle;
NSLog(@"or:%@",[or meetCriteria:list1]);
步骤 5
执行程序,输出结果:
2019-05-21 17:55:31.172443+0800 test[82594:19349590] Males:(
"<Person_2: 0x6000001a00e0>"
)
2019-05-21 17:55:31.172659+0800 test[82594:19349590] Single:(
"<Person_2: 0x6000001a00e0>",
"<Person_2: 0x6000001a0100>"
)
2019-05-21 17:55:31.172819+0800 test[82594:19349590] and:(
"<Person_2: 0x6000001a00e0>"
)
2019-05-21 17:55:31.172955+0800 test[82594:19349590] or:(
"<Person_2: 0x6000001a00e0>"
)
过滤器比较简单,就是将过滤的条件封装成抽象类,然后继承这个抽象类,可以封装各种各样的条件,最终返回想要的结果。
参考资料
runoob