黑马程序员_代理设计模式

时间:2021-12-07 12:01:22

------Java培训、Android培训、iOS培训、.Net培训、期待与您交流!


一.使用场景

1.现实生活中,我们遇到一些很麻烦的事情要处理,但是自己又没有时间去做,比如说我们每天都要去上班,但是需要打扫家里的卫生,喂狗,洗衣等工作,总之有很多工作我们没时间亲自去做后者不想亲自去做,这时我们想到的解决办法就是找一个人代替我们去做这些事情,只要这个人会打扫卫生,会喂狗,会洗衣服就是我们想要的。我们将代替我们处理事情的这个人称为代理。把这个问题模拟到程序中,我们通过代理设计模式解决这类问题。


二.初步实现代理模式


1.设计一个代理Agent

 1>根据我们的需要,只要一个人会打扫卫生,喂狗,洗衣服这些工作,那么这个人就可以成为我们的代理。所以代理类中必须拥有我们需要的功能。我们只在乎代理的功能是否满足我们的需求。

//  Agent.h

#import <Foundation/Foundation.h>

@interface Agent : NSObject
// 打扫卫生
- (void)daSaoWeiSheng;

// 喂狗
- (void)weiGou;

// 洗衣服
- (void)xiYiFu;

@end

//  Agent.m

#import "Agent.h"

@implementation Agent
// 打扫卫生
- (void)daSaoWeiSheng
{
    NSLog(@"完成打扫卫生的工作。");
}

// 喂狗
- (void)weiGou
{
    NSLog(@"完成喂狗的工作。");
}

// 洗衣服
- (void)xiYiFu
{
    NSLog(@"完成洗衣服的工作。");
}

@end

2.设计一个Person类用于我们 自己

 1>在类的接口部分,我们需要定义代理属性,持有对代理对象的引用(就好比我们雇佣了一个清洁工)。

 2>我们定义打扫卫生,喂狗,洗衣服的方法。

 3>在方法的实现中,真实工作并不是由我们去做,而是我们拥有的代理去做,代理会调用自己的方法去完成这些工作(就好比我们对清洁工说:开始做工作了)。

//  Person.h

#import <Foundation/Foundation.h>
@class Agent;

// Person
@interface Person : NSObject

// 拥有一个代理属性
@property (nonatomic, strong) Agent *agent;

// 打扫卫生
- (void)daSaoWeiSheng;

// 喂狗
- (void)weiGou;

// 洗衣服
- (void)xiYiFu;
@end

//  Person.m

#import "Person.h"
#import "Agent.h"

@implementation Person

// 打扫卫生
- (void)daSaoWeiSheng
{
    // 调用代理自己的方法
    [_agent daSaoWeiSheng];
}

// 喂狗
- (void)weiGou
{
    // 调用代理自己的方法
    [_agent weiGou];
}

// 洗衣服
- (void)xiYiFu
{
    // 调用代理自己的方法
    [_agent xiYiFu];
}
@end

//  main.m

#import <Foundation/Foundation.h>
#import "Person.h"
#import "Agent.h"

int main(int argc, const char * argv[])
{
    Person *p = [[Person alloc] init];
    
    // 创建代理对象
    Agent *agent = [[Agent alloc] init];
    
    // 持有代理
    p.agent = agent;
    
    [p xiYiFu];
    [p weiGou];
    [p daSaoWeiSheng];
    /*
    运行结果:
     代理-完成洗衣服的工作。
     代理-完成喂狗的工作。
     代理-完成打扫卫生的工作。
    */
    return 0;
}

3.设计缺陷

从main函数的运行结果看,代理很出色的完成了他的任务。但是我们发现这个代理的工作做的很粗糙,我们想更换掉它,这时问题来了,我们除了需要新设计一个代理,还要在Person类中改动代码,更换持有的代理属性。这在程序设计中是一个很糟糕的问题,这个设计的耦合性太强了。


三.完善代理模式

1.完善设计

 1>首先我们思考,我们只需要知道当我们的代理只要拥有我们需求的功能就可以,而具体代理是谁,我们并不需要知道。所以我们需要有一个规范,这个规范里有我们对代理的要求,只要遵守这个规范就可以成为我们的代理。我们通过定义一个协议来实现这个规范。


 2>定义一个协议

只要遵守了这个协议就能成为我们的代理。

//  WorksDelegate.h

#import <Foundation/Foundation.h>

@protocol WorksDelegate <NSObject>
// 打扫卫生
- (void)daSaoWeiSheng;

// 喂狗
- (void)weiGou;

// 洗衣服
- (void)xiYiFu;
@end


 3>修改Agent

//  Agent.h

#import <Foundation/Foundation.h>
#import "WorksDelegate.h"

// Agent遵守了WorksDelegate协议
@interface Agent : NSObject <WorksDelegate>

@end

//  Agent.m

#import "Agent.h"

// 实现协议中的方法
@implementation Agent
// 打扫卫生
- (void)daSaoWeiSheng
{
    NSLog(@"代理-完成打扫卫生的工作。");
}

// 喂狗
- (void)weiGou
{
    NSLog(@"代理-完成喂狗的工作。");
}

// 洗衣服
- (void)xiYiFu
{
    NSLog(@"代理-完成洗衣服的工作。");
}

@end

 4>修改Person

  1)将代理属性改为:@property (nonatomic, strong) id<WorksDelegate> agent; 任何一个遵守了WorksDelegate协议的类型的对象都可以成为我们的代理。

//  Person.h

#import <Foundation/Foundation.h>
#import "WorksDelegate.h"

// Person
@interface Person : NSObject

// 拥有一个代理属性
@property (nonatomic, strong) <strong>id<WorksDelegate> agent</strong>;

// 打扫卫生
- (void)daSaoWeiSheng;

// 喂狗
- (void)weiGou;

// 洗衣服
- (void)xiYiFu;
@end

2.这样,我们将Person与代理之间的耦合性大大减少,不论怎么更换代理都不用改动Perosn类的代码。任何一个遵守了协议的对象都可以成为代理。


四.代理模式的几个要素

1.定义一个协议,在其中声明一些和代理沟通的方法

2.拥有一个代理属性,id<property> agent

3.代理必须遵守protocol