设计模式-简单工厂模式+反射机制
程序员文章站
2022-03-09 20:29:38
...
写在前面
上一篇工厂模式我们了解了简单工厂模式与工厂模式各自的优缺点,那么有没有一种设计思路可以
- 能扩展新的运算模式
- 不用去直接修改工具类
- 不用给新的扩展类新增工具类
当然是可以的,这就是本文的价值
了解OC层面的反射机制
Objective-C 反射篇
Objective-C语言中的OC对象,都继承自NSObject类。这个类为我们提供了一些基础的方法和协议,我们可以直接调用从这个类继承过来方法。这里的反射方法,就在NSObject和Foundation框架中,不涉及runtime部分。
获取Class对象
Class对象其实本质上就是一个结构体,这个结构体中的成员变量还是自己,这种设计方式非常像链表的数据结构。
typedef struct objc_class *Class;
struct objc_class {
Class isa OBJC_ISA_AVAILABILITY;
}
可以直接用一个实例对象或类对象,直接调用Class方法,都可以获取Class对象。
反射方法
系统Foundation框架为我们提供了一些方法反射的API,我们可以通过这些API执行将字符串转为SEL等操作。由于OC语言的动态性,这些操作都是发生在运行时的。
// SEL和字符串转换
FOUNDATION_EXPORT NSString *NSStringFromSelector(SEL aSelector);
FOUNDATION_EXPORT SEL NSSelectorFromString(NSString *aSelectorName);
// Class和字符串转换
FOUNDATION_EXPORT NSString *NSStringFromClass(Class aClass);
FOUNDATION_EXPORT Class __nullable NSClassFromString(NSString *aClassName);
// Protocol和字符串转换
FOUNDATION_EXPORT NSString *NSStringFromProtocol(Protocol *proto) NS_AVAILABLE(10_5, 2_0);
FOUNDATION_EXPORT Protocol * __nullable NSProtocolFromString(NSString *namestr) NS_AVAILABLE(10_5, 2_0);
通过这些方法,我们可以在运行时选择创建那个实例,并动态选择调用哪个方法。这些操作甚至可以由服务器传回来的参数来控制,我们可以将服务器传回来的类名和方法名,实例为我们的对象。
// 假设从服务器获取JSON串,通过这个JSON串获取需要创建的类为ViewController,并且调用这个类的getDataList方法。
Class class = NSClassFromString(@"ViewController");
ViewController *vc = [[class alloc] init];
SEL selector = NSSelectorFromString(@"getDataList");
[vc performSelector:selector];
反射机制的使用
简单工厂模式的工具类写法如下,这种每新增一种运算模式,就要在工具类里增加一个分支,不仅违背了开放-封闭原则,还要每次做多次判断,及其不友好。
@implementation ZYCountTool
+ (ZYCount *)creatCountForOperation:(NSString *)operationStr
{
if ([operationStr isEqualToString:@"+"]) {
return [[ZYCountAdd alloc] init];
}
else if ([operationStr isEqualToString:@"-"]) {
return [[ZYCountSubtractor alloc] init];
}
else if ([operationStr isEqualToString:@"*"]) {
return [[ZYCountMuli alloc] init];
}
return [[ZYCountDivision alloc] init];
}
@end
反射机制的写法如下,工具类根据传入的类名,生成对应的运算类,完成运算。新增运算模式时只需要扩展运算类,不用新增对应的子工具类,不用修改父工具类,直接在客户端传入运算类名完成调用。
@implementation ZYCountTool
/**
@param operationStr 运算类的类名
*/
+ (ZYCount *)creatCountForOperation:(NSString *)operationStr
{
Class class = NSClassFromString(operationStr);
ZYCount *count = [[class alloc] init];
return count;
}
@end
上一篇: 反射 内省 JaveBean 与 简单工厂设计模式
下一篇: 用Java反射优化工厂设计模式