代理模式

作者: 952625a28d0d | 来源:发表于2015-11-19 10:17 被阅读303次
  • 代理模式
  • 代理与协议
  • 用NSProxy实现代理模式
Paste_Image.png
  • 代理模式的基本原理
    代理模式实际上就是一个对象和另外一个对象的耦合,我们为了降低耦合度。用抽象的代理来实现功能。

  • 使用代理模式需要注意的地方
    weak 是否响应

  • 经销商和顾客
    假设主控制器ViewController是经销商,我们来写一个顾客类 然后写一个ViewController属性
    然后写一个方法用来调用ViewController方法,同时传递顾客买东西行为,和数量

// 顾客
#import <Foundation/Foundation.h>
#import "ViewController.h"

@interface Custmer : NSObject

@property (nonatomic, weak) ViewController *viewController;

// 顾客买卖行为
- (void)custmerBuyActionWithCount:(NSInteger)count;

@end```

import "Custmer.h"

@implementation Custmer

  • (void)custmerBuyActionWithCount:(NSInteger)count{
    if (self.viewController) {
    // 购买数量传递给经销商
    [self.viewController custmerBuyActionsWithCount:count];
    }
    }
    @end```

  • 经销商(ViewController)

#import <UIKit/UIKit.h>

@interface ViewController : UIViewController

- (void)custmerBuyActionsWithCount:(NSInteger)count; (接收方法)

@end```

import "ViewController.h"

import "Custmer.h"

// 经销商
@interface ViewController ()

@end

@implementation ViewController

  • (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.

    Custmer *custmer = [[Custmer alloc] init];
    custmer.viewController = self; (指定经销商)
    [custmer custmerBuyActionWithCount:5];
    }

// 实现传递方法传递过来的值

  • (void)custmerBuyActionsWithCount:(NSInteger)count{
    NSLog(@"%ld",count);
    }

  • (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
    }

@end```

  • 运行结果:
Paste_Image.png
  • 上面我们用了一个简单的例子说明了代理的原理,我们用一个对象去弱引用另一个对象,为这个对象传值,通过调用本对象的方法来实现给另一个对象传值,从而实现对象间互通。
    但是这里的经销商是一个指定的对象,但是我们写代码的时候如果有不同的对象需要知道该顾客的行为呢?

  • 下面我们来修改使其成为一个通用的代理

// 顾客
#import <Foundation/Foundation.h>
#import "ViewController.h"

@class Custmer; // 声明下面出现的类
@protocol custmerDelegate <NSObject>

@required
- (void)custmerBuyWithCount:(NSInteger)count custmer:(Custmer *)custmer;    // 必须实现的代理方法

@end

@interface Custmer : NSObject

@property (nonatomic, weak) id<custmerDelegate> delegate;   // 弱引用的代理属性

// 顾客买卖行为
- (void)custmerBuyActionWithCount:(NSInteger)count; // 调用方法

@end```

import "Custmer.h"

@implementation Custmer

  • (void)custmerBuyActionWithCount:(NSInteger)count{
    // 如果代理存在 并且可以响应代理方法
    if (self.delegate && [self.delegate respondsToSelector:@selector(custmerBuyWithCount:custmer:)]) {
    // 执行代理方法
    [self.delegate custmerBuyWithCount:count custmer:self];
    }
    }

@end```

#import "ViewController.h"
#import "Custmer.h"

// 经销商
@interface ViewController ()<custmerDelegate>   // 遵守代理

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
    
    Custmer *custmer = [[Custmer alloc] init];
    custmer.delegate = self;    // 设置代理
    [custmer custmerBuyActionWithCount:5];  
}

#pragma mark 实现代理方法
- (void)custmerBuyWithCount:(NSInteger)count custmer:(Custmer *)custmer{
    NSLog(@"%ld~~%@",count,custmer);
}

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

@end```

- 运行结果:

![Paste_Image.png](http:https://img.haomeiwen.com/i189984/62cf6595279d2e0d.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

以上我们就实现了一个通用的代理。
也就是说现在Customer可以服务的对象是任何遵守了他的协议的对象。这就降低了对象与对象之间的耦合度,我们的代理并不用关心使用的对象是谁,而要关心是否遵守了代理协议并设置了代理对象。
使用代理的时候一定要注意一下几点:
1:声明协议的时候经常需要将代理对象传递出去,所以用@class进行声明。
2:避免循环引用,所以属性一定要写成weak
3:写代理方法的时候要写明白是requied还是option
4:使用代理的时候一定要验证代理是否存在并且是否可以执行代理方法,不然可能造成不必要的崩溃。

#####代理与协议的区别
- 代理的职能
降低对象之间的耦合度
- 协议
约束对象、筛选对象
- 相似性:
他们两者都是用protocol声明

下面我们来创建一个协议:


![Paste_Image.png](http:https://img.haomeiwen.com/i189984/e80cb6b33cf39ce7.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

import <Foundation/Foundation.h>

@protocol TCPProtocol <NSObject>

@required

  • (NSInteger)sourcePort; // 获取源端口号

  • (NSInteger)destinationPort; // 获取目的地端口号

@end```

  • 引入协议


    Paste_Image.png
  • 使用协议

#pragma mark - 获取协议的源端口号和目的地端口号
- (void)accessTCPData:(id<TCPProtocol>)data{
    self.sourcePort = [data sourcePort];
    self.destinationPort = [data destinationPort];
}```

 - 如果一个模型遵循了我们写的协议

import <Foundation/Foundation.h>

import "TCPProtocol.h"

@interface Model : NSObject<TCPProtocol>

@end```

#import "Model.h"

@implementation Model

#pragma mark - 实现协议方法
- (NSInteger)sourcePort{
    return 10;
}// 获取源端口号

- (NSInteger)destinationPort{
    return 10;
}// 获取目的地端口号

@end```

那么我们以上在ViewController里面获取协议源端口号和目的地端口号则可以用Model中所实现的协议方法中的值,因为Model实现了协议方法。
所以说协议是为了约束对象。规范接口。和代理是完全不一样的。

#####用NSProxy来实现代理模式
NSProxy是一个继承于NSObject的类 

- NSProxy中的消息传递机制
- NSProxy的用途
- 用NSProxy来实现代理模式

1:首先写一个继承自NSProxy的类

import <Foundation/Foundation.h>

@interface AbastarctProxy : NSProxy

@property (nonatomic, weak) id delegate;

@end```

#import "AbastarctProxy.h"
#import "AbastarcExcute.h"
#import <objc/runtime.h>

@implementation AbastarctProxy

#pragma mark - 验证方法签名
- (nullable NSMethodSignature *)methodSignatureForSelector:(SEL)sel{
    if ([self.delegate respondsToSelector:sel]) {
        return [self.delegate methodSignatureForSelector:sel];
    }else{
        
        // 方法签名扔到处理专门处理的单例类中
        AbastarcExcute *excute = [AbastarcExcute shareInstance];
        return [excute methodSignatureForSelector:NSSelectorFromString(@"nullExcute:")];
    }
}

#pragma mark 派发信息
- (void)forwardInvocation:(NSInvocation *)invocation{
    
    // 获取方法
    SEL selecter = [invocation selector];
    // 如果代理能够响应方法
    if ([self.delegate respondsToSelector:selecter] ) {
        // 设置代理
        [invocation setTarget:self.delegate];
        // 执行方法
        [invocation invoke];
    }else{
        // 获取没有替换之前的selector
        NSString *selectorString = NSStringFromSelector(invocation.selector);
        invocation.selector = NSSelectorFromString(@"nullExcute:");
        AbastarcExcute *excute = [AbastarcExcute shareInstance];
        [invocation setTarget:excute];
        const char *className = class_getName([self class]);    // 获取当前的class类
        NSArray *infos = nil;
        if (self.delegate) {
            infos = @[[NSString stringWithUTF8String:className],selectorString,@""];
        }else{
            infos = @[[NSString stringWithUTF8String:className],selectorString];
        }
        [invocation setArgument:&infos atIndex:2];
        [invocation invoke];
    }
}

@end```

2:写一个处理垃圾消息的单例类即没有代理或者代理不响应协议方法的时候

// 处理垃圾消息的类

import <Foundation/Foundation.h>

@interface AbastarcExcute : NSObject

  • (instancetype)shareInstance;

@end```

#import "AbastarcExcute.h"

@implementation AbastarcExcute

+ (instancetype)shareInstance{
    static AbastarcExcute *excute = nil;
    static dispatch_once_t predicate;
    dispatch_once(&predicate, ^{
        excute = [[AbastarcExcute alloc] init];
    });
    return excute;
}

- (void)nullExcute:(NSArray *)infos{
    NSLog(@"%@",infos);
}

@end```

3:写一个协议

import <Foundation/Foundation.h>

@protocol MessageProtocol <NSObject>

@optional

  • (void)helloWolrd;
  • (void)goodBey;

@end```

4:写一个类遵守该协议

#import "AbastarctProxy.h"
#import "MessageProtocol.h"

@interface ConcreatProxy : AbastarctProxy<MessageProtocol>

@end```

import "ConcreatProxy.h"

@implementation ConcreatProxy

@end```

5:主控制器调用

#import "ViewController.h"
#import "ConcreatProxy.h"

@interface ViewController ()<MessageProtocol>

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
    
    ConcreatProxy *proxy = [ConcreatProxy alloc];   // 这个代理只有alloc方法
    proxy.delegate = self;
    [proxy helloWolrd]; // 让代理执行helloworld
}

- (void)helloWolrd{
    NSLog(@"xxxxx");
}

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

@end```

6:输出结果

![Paste_Image.png](http:https://img.haomeiwen.com/i189984/5e254fbd3d2d18d1.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

#####需要掌握的
- 代理模式
- 代理与协议的区别
- 用NSProxy实现代理模式

相关文章

  • 设计模式

    单例模式 模板方法模式 工厂模式 代理模式 静态代理 JDK动态代理

  • 设计模式

    单例模式 代理模式 静态代理 jdk动态代理 cglib动态代理 工厂模式 适配器模式 建造者模式 观察者模式

  • kube-proxy的3种模式

    userspace代理模式 iptables代理模式 IPVS代理模式 https://kubernetes.io...

  • 第4章 结构型模式-代理模式

    一、代理模式简介 二、代理模式3个角色 三、代理模式的优点 四、代理模式的实例(游戏代练)

  • 理解代理模式

    原创博客地址 简介 代理模式,也叫做委托模式,分为:静态代理动态代理 代理模式也是平时比较常用的设计模式之一,代理...

  • 结构型 代理模式(文末有项目连接)

    1:什么是代理模式 2:没用代理模式时的实例 3:使用代理模式将其解耦(静态代理) 3:使用代理模式将其解耦(动态...

  • 设计模式-动态代理模式

    之前介绍了代理模式,大家也都了解了代理模式,不过之前介绍的代理模式是静态代理,静态代理什么意思?静态代理指的是代理...

  • 代理模式

    一、什么是代理模式 代理模式(Proxy pattern):代理模式又叫委托模式,是为某个对象提供一个代理对象,并...

  • 设计模式之代理模式(Proxy模式)

    代理模式的引入 代理模式的实例程序 代理模式的分析 代理模式的引入 Proxy是代理人的意思,指的是代替别人进行工...

  • Java设计模式之代理模式

    Java设计模式之代理模式 代理模式 静态代理 动态代理 为什么需要代理 通过代理,我们能够不用知道委托人是谁,而...

网友评论

    本文标题:代理模式

    本文链接:https://www.haomeiwen.com/subject/xuxkhttx.html