欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

设计模式-简单工厂模式+反射机制

程序员文章站 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