iOS 设计模式的应用 ⑳ 代理模式

前言

    在 Windows 系统中,我们安装软件时,常常会遇见在桌面安装快捷方式,让我们更快捷的找到它,当我们运行它时实际上是访问到了该文件的实际位置。在 Mac 中也有这种设计叫做替身。如果我们不创建快捷方式,就要去寻找应用程序所在的真实路径,才可以运行,这会给我们带来许多的麻烦。

    在面向对象的软件设计中,有些对象由于某些原因(比如对象创建开销很大,或者某些操作需要安全控制,或者需要进程外的访问),直接访问会给使用者或者系统结构带来很多麻烦,我们可以在访问此对象时加上一个对此对象的访问层。从这一思想细化而来的一种设计模式叫做代理模式

什么是代理模式

    代理模式为其他对象提供一种代理以控制对这个对象的访问。通常,代理是一种替代或者占位,它控制对另一些对象的访问,而这些对象可能是远程对象、创建开销较大的对象,或者是对安全性有要求的对象。代理模式的思想是使用一个基本上跟实体对象行为相同的代理。客户端可以透明地使用代理,不必执行所面对的只是一个代理而不是实体对象。当客户端请求某些创建开销较大的功能时,代理将把请求转发给实体对象,准备好请求的功能并返回给客户端。

代理模式的类图.png

    当客户端向 Proxy对象发送request 消息时,Proxy 对象会把这个消息转发给 Proxy对象之中的 RealSubject 对象。 RealSubject会实施实际的操作间接满足客户端的请求。

什么时候使用代理模式

  • 远程代理
  • 虚拟代理
  • 保护代理
  • Cache 代理
  • 防火墙代理
  • 同步化代理
  • 智能引用代理

代理模式的优缺点

代理模式的优点

  1. 职责清晰。
  2. 高扩展性。
  3. 智能化。

代理模式的缺点

  1. 由于在客户端和真实主题之间增加了代理对象,因此有些类型的代理模式可能会造成请求的处理速度变慢。
  2. 实现代理模式需要额外的工作,有些代理模式的实现非常复杂。

Cocoa 中的代理模式

    NSProxy 是 Cocoa 框架中如 NSObject 一样的根类,定义了充当其他对象代理的对象的接口,即使对于尚不存在的对象也是如此。代理对象通常将发送给它的消息转发给它所代表的对象,但它也可以通过加载所表示的对象或将自己转换成它来响应消息。虽然NSProxy是一个抽象类,但它实现NSObject了根对象所期望的协议和其他基本方法,NSProxy 的具体子类可以实现代理模式的既定目标。

代理模式的实现

声明一个 协议

@protocol Image 

- (void)display;

@end

创建一个 RealImage 实体类

@interface RealImage : NSObject

- (instancetype)initWithFileName:(NSString *)fileName;

@end
@implementation RealImage
{
    NSString *_fileName;
}

- (instancetype)initWithFileName:(NSString *)fileName
{
    self = [super init];
    if (self) {
        _fileName = fileName;
    }
    return self;
}
    
- (void)display{
    NSLog(@"display%@",_fileName);
}

- (void)loadFromDisk{
    NSLog(@"loadFrom%@",_fileName);
}

@end

创建一个 ProxyImage 代理类

@interface ProxyImage : NSProxy

- (instancetype)initWithFileName:(NSString *)fileName;

@end
@implementation ProxyImage{
    RealImage *_realImage;
    NSString *_fileName;
}

- (instancetype)initWithFileName:(NSString *)fileName
{

    _fileName = fileName;
    return self;
}

- (void)forwardInvocation:(NSInvocation *)invocation{
    SEL aSelector = [invocation selector];
    if (_realImage && [_realImage respondsToSelector:aSelector]) {
        [invocation invokeWithTarget:_realImage];
    }else{
        [super forwardInvocation:invocation];
    }
}

- (NSMethodSignature *)methodSignatureForSelector:(SEL)sel{
    if (!_realImage) {
        _realImage = [[RealImage alloc] initWithFileName:_fileName];
    }
    if ([_realImage respondsToSelector:sel]) {
        NSMethodSignature *signature = [_realImage methodSignatureForSelector:sel];
        return signature;
    }
    return [super methodSignatureForSelector:sel];
}

@end

总结

    代理对象,以控制对另一个对象的访问,该对象可能是远程的、创建成本高昂或需要保护。这种模式在结构上类似于装饰器模式,但它的用途不同;装饰器向对象添加行为,而代理控制对对象的访问。
    在 iOS 应用开发中,总是要关注内存的使用量。不论应用程序运行在何种 iOS 设备上,出于性能的考虑,总是推荐懒加载技术。可以在 iOS 应用中使用代理模式,对开销大的数据实现懒加载,如大图像文件或者通过低俗网络从服务器下载的大型数据。如果大开销的对象在收到请求之间不需要加载,通过虚拟代理向客户端提供某些轻量信息。

你可能感兴趣的:(iOS 设计模式的应用 ⑳ 代理模式)