Objective-C 编程之道 iOS设计模式解析--第22章 代理

来源:互联网 发布:mac 10.13.1 卡 编辑:程序博客网 时间:2024/05/19 02:03

22代理

22.1 何为代理模式

远程代理(remote proxy)为位于不同地址空间或网络上的对象提供本地代表。

虚拟代理(virtual proxy)根据需要创建重型对象。

保护代理(protection proxy)根据各种访问权限控制对原对象的访问。

智能引用代理(smart-reference proxy)通过对真正对象的引用进行计数管理内存。也用于锁定真正对象,让其他对象不能对其进行修改。

代理模式:为其他对象提供一种代理一控制对这个对象的访问。


通常,代理是一种代替活着占位,她控制对另一个对象的访问,而这些对象可能是远程对象,创建的开销较大的对象,或者是对安全性有要求的对象。这里没有办法对这些代理作一一介绍。



在运行时,我们可以想象这样一个场景:客户端一抽象类型引用一个对象。这个引用实际上是个Proxy对象。Proxy对象本身有一个对RealSubject实例的引用,以后如果接到请求,此实例将执行高强度的工作。



22.2 何时使用代理模式

22.3 用虚拟代理懒加载图像

涂鸦缩略图视图的设计与实现

//———————————————

@interface ScribbleThumbnailView : UIView

{

    @protected

    NSString *imagePath_;

}

@property (nonatomic,readonly) UIImage *image;

@property (nonatomic,copy) NSString *imagePath;

@end


#import “ScribbleThumbnailView.h”

#implementation ScribbleThumbnailView

@dynamic image;

@synthesize imagePath= imagePath_;

@end

//———————————————

#import “ScribbleThumbnailView.h”

@interface ScribbleThumbnailViewImageProxy : ScribbleThumbnailView

{

    @private

    UIImage *realImage_;

    BOOL loadingThreadHasLaunched_;

}

@property (nonatomic, readonly) UIImage *image;

@end;


#import “ScribbleThumbnailViewImageProxy.h”

@interface ScribbleThumbnailViewImageProxy()

-(void) forwardImageLoadingThread;

@end


@implementation ScribbleThumbnailViewImageProxy

@dynamic imagePath;


- (UIImage*)image

{

    if (realImage_ == nil)

    {

        realImage_ = [[UIImage alloc] initWithContentOfFile:imagePath_];

    }

    return realImage_;

}


- (void)drawRect:(CGRect)rect

{

    if (realImage_ == nil)

    {

        //绘制占位图像

    }


    if(!loadingThreadHasLaunched_)

    {

        [self performSelectorInBackground:@select(forwardImageLoadingThread) withObject:nil];

        loadingThreadHasLaunched_ = YES;

    }

    else

    {

        [realImage_ drawInRect:rect];

    }

}


- (void)dealloc

{

    [realImage_ realease];

    [super dealloc];

}


-(void) forwardImageLoadingThread

{

    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];

    [self image];

    [self performSelectorInMainThread:@selector(setNeedsDispaly) withObject:nil];

    [pool release];

}

@end

//———————————————

22.4 在Cocoa Touch框架中使用代理模式


//—————————————————————————

MyProtocol.h

//

//  MyProtocol.h

//  NSProxyTest

//

//  Created by ranzhou on 16/7/6.

//  Copyright © 2016 ranzhouee. All rights reserved.

//


#import <Foundation/Foundation.h>


@protocol MyProtocol <NSObject>


@optional

-(void)loadImage;


@required


@end

//—————————————————————————

//

//  RealObject.h

//  NSProxyTest

//

//  Created by ranzhou on 16/7/6.

//  Copyright © 2016 ranzhouee. All rights reserved.

//


#import <Foundation/Foundation.h>

#import "MyProtocol.h"

@interface RealObject : NSObject<MyProtocol>


@end

//—————————————————————————

//

//  RealObject.m

//  NSProxyTest

//

//  Created by ranzhou on 16/7/6.

//  Copyright © 2016 ranzhouee. All rights reserved.

//


#import "RealObject.h"


@implementation RealObject

-(void)loadImage

{

    staticdispatch_once_t once;

    dispatch_once(&once, ^{

        [NSThreadsleepForTimeInterval:5.0];

        // 第一次加载图像,需要5秒钟。

    });

    NSLog(@"%@%@",NSStringFromClass([selfclass]),NSStringFromSelector(_cmd));

}

@end

//—————————————————————————

//

//  TestProxy.h

//  NSProxyTest

//

//  Created by ranzhou on 16/7/6.

//  Copyright © 2016 ranzhouee. All rights reserved.

//


#import <Foundation/Foundation.h>

#import "MyProtocol.h"


@interface TestProxy : NSProxy<MyProtocol>


//TestProxy中需要实现初始化方法,否则 self.testProxy = [[TestProxy alloc]init];或报编译错误//No visible @interface for 'TestProxy' declares the selector 'init';

//- (instancetype)init;//个人觉得不init也无所谓。


@end

//—————————————————————————

//

//  TestProxy.m

//  NSProxyTest

//

//  Created by ranzhou on 16/7/6.

//  Copyright © 2016 ranzhouee. All rights reserved.

//


#import "TestProxy.h"

#import "RealObject.h"


@interface TestProxy ()

@property (nonatomic,strong) RealObject *realObject;

@end


@implementation TestProxy


- (RealObject*)toInitRealObject {

    static dispatch_once_t once;

    dispatch_once(&once, ^{

        if (!self.realObject) {

            self.realObject = [[RealObject alloc]init];

        }

    });

    returnself.realObject;

}


- (void)loadImage {

    if (!self.realObject)

    {

        NSLog(@"随便做点事情,等self.realObject初始化完成再处理");

        dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0), ^{

            [selftoInitRealObject];

            [self.realObjectloadImage];

        });

    }

    else

    {

        [self.realObjectloadImage];

    }

}


- (void)forwardInvocation:(NSInvocation *)invocation

{

    if (self.realObject)

    {

        [invocation setTarget:self.realObject];

        [invocation invoke];

    }

    else

    {

        NSLog(@"%@%@",@"self.realObject is nil",NSStringFromSelector(_cmd));

    }

}


- (nullable NSMethodSignature *)methodSignatureForSelector:(SEL)sel

{

    if (self.realObject) {

        return [self.realObject methodSignatureForSelector:sel];

    }

    else

    {

        NSLog(@"%@%@",@"self.realObject is nil",NSStringFromSelector(_cmd));

        return [super methodSignatureForSelector:sel];

    }

}


@end

//—————————————————————————

测试代码:

    self.testProxy = [TestProxyalloc];

    [self.testProxyloadImage];

    [self.testProxyloadImage];

}


2016-07-06 21:15:26.276 NSProxyTest[1684:298600] 随便做点事情,等self.realObject初始化完成再处理

2016-07-06 21:15:26.277 NSProxyTest[1684:298600] 随便做点事情,等self.realObject初始化完成再处理

2016-07-06 21:15:31.279 NSProxyTest[1684:298671] RealObjectloadImage

2016-07-06 21:15:31.279 NSProxyTest[1684:298663] RealObjectloadImage

//—————————————————————————

0 0