编写高质量代码的52个有效方法

52个有效方法(23) - 通过委托与数据协议进行对象间的通信

2018-09-05  本文已影响14人  SkyMing一C
委托模式(Delegate pattern)

委托模式(Delegate pattern):用来实现对象间的通信

委托模式的主旨

定义一套接口,某对象若想授受另一个对象的委托,则需遵从此接口,以便成为其“委托对象”(delegate)。而这“另一对象”则可以给其委托对象回传一些消息,也可以在发生相关事件时通知委托对象。

委托模式可以将数据与业务逻辑解耦

由数据源(data source)与委托(delegate)对象分别处理。

数据源和受委托者可以是两个不同的对象。然而一般情况下,都用同一个对象来扮演这两种角色。

在数据源模式中,信息从数据源(Data Source)流向类(Class);而在常规的委托模式中,信息则从类流向受委托者(Delegate)

委托协议

在Objective-C中,一般通过协议(protocol)这项语言特性来实现此模式,它与Java的“接口”(interface)类似。Objective-C不支持多继承,但可以把类的实现方法定义在协议里面。

委托协议命名

回调委托对象的流程

回调委托对象的流程

回调委托对象的流程 :EOCDataModel对象就是EOCNetworkFetcher的委托对象。EOCDataModel请求EOCNetworkFetcher"以异步方式执行一项任务"(perform a task asynchronously),而EOCNetworkFetcher在执行完这项任务之后,就会通知其委托对象EOCDataModel

有了协议后,类就可以用一个属性来存放其委托对象了。

@property(nonatomic, weak) id<类名+Delgate> delegate;

@optional关键字(可选的)

在委托对象上调用可选方法时必须提前使用类型信息查询方法(参见第14条)来判断这个委托对象能否响应相关选择子。(注意:如果不是可选方法,则不需要。

// 注意:如果不是可选方法,则不需要。
if([_delegate respondsToSelector:@selector(委托方法)]) {

  [_delegate 委托方法];

}

选择子判断的优化

有时除了第一次检测的结果有用之外,后续的检测可能是多余的。对于频繁的检测,也消耗性能。

对此可以优化:把委托对象能否响应某个协议方法这一信息缓存起来。

将方法响应能力缓存起来的最佳人途径是使用“位段”(bitfield)数据类型。这是一项无人问津的C语言特性。

位段: 把结构体中某个字段所占用的二进制位个数设为特定的值。

struct data {

  unsigned int fieldA: 8; // 表示0~255之间的值

  unsigned int fieldB: 4;

  unsigned int fieldC: 2;

  unsigned int fieldD: 1; // 表示0或1

}

这样就可以嵌入一个含有位段的结构体作为实例变量,而结构体中的每个位段表示delegate对象是否实现了协议中的相关方法。(类似字典)

struct {

  unsigned int didReceiveData: 1;

  unsigned int didFailWithError: 1;

  unsigned int didUpdateProgressTo: 1;

} _delegateFlags;

-(void)setDelegate:(id<协议> delegate){

  _delegate = delegate;

  _delegateFlags.didReceiveData = [@delegate respondsToSelector:@selector(方法)]; // 值为:0或1

  // ……

}

if(_delegateFlags.didReceiveData) {

  [_delegate 方法]  

}

delegate对象可以有多个,所以在定义或调用时,应该把发起委托的类或实例加入进去。

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {

  if(tableView == tableViewA){

  }else if(tableView == tableViewA){

  }

}
关键字
要点
  1. 委托模式为对象提供了一套接口,使其可由此相关事件告知其他对象。

  2. 将委托对象应该支持的接口定义成协议,在协议中把可能需要处理的事件定义成方法。

  3. 当某个对象需要从另一个对象中获取数据时,可以使用委托模式。这种情景下,该模式亦称“数据源协议”(data source protocal)。

  4. 若有必要,可实现含有位段的结构体,将委托对象是否能响应相关协议方法这一信息缓存至其中。

上一篇 下一篇

猜你喜欢

热点阅读