------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