对于iOS开发,举例Cocoa框架下的几个设计模式为大家分析。当然,Cocoa框架下关于设计模式的内容远远不止这些,我们选择了常用的几种:单例模式、委托模式、观察者模式、MVC模式。

委托模式

委托模式从GoF 设计装饰(Decorator)、适配器(Adapter)和模板方法(Template Method)等模式演变而来。几乎每一个应用都会或多或少地使用到委托模式。不只是CocoaTouch框架,在Cocoa框架中委托模式也得到了广泛的应用。

问题提出

对于应用生命周期的非运行状态——应用启动场景,我们把从点击图标到第一个画面启动的过程细化了一下

假设上图这一系列的处理,都是在一个上帝类UIApplication完成的。之所以叫“上帝类(God Class)”,是因为它“无所不能”、“包含所有”。在面向对象的软件设计中“上帝类”不是很友好,需要重构。在编程过程中要尽量避免上帝类的使用,因为上帝类是高耦合的,职责不清,所以难以维护。我们需要“去除上帝类”,把看似功能很强且很难维护的类,按照职责把自己的属性或方法分派到各自的类中或分解成功能明确的类,从而去掉“上帝类”。

幸运的是苹果没有把UIApplication类设计成“上帝类”,苹果处理分割到两个不同的角色类中,其中一个扮演框架类角色,框架类具有通用、可重复使用、与具体应用无关等特点。另一个扮演应用相关类的角色,应用相关类与具体应用有关,由于要受到框架类的控制,常常被设计成为“协议”,在Java中称之为“接口”。开发人员需要在具体的应用中实现这个“协议”。

将application:didFinishLaunchingWithOptions:和applicationDidBecomeActive:完成功能提取出来,定义在UIApplicationDelegate协议中,这样UIApplication类就变成了框架类。

在具体使用时候需要实现UIApplicationDelegate协议,HelloWorld应用的类图。UIApplication不直接依赖于AppDelegate类,而是依赖于UIApplicationDelegate协议,这在面向对象软件设计原则中叫做“面向接口的编程”。AppDelegate类实现协议UIApplicationDelegate,它是委托类。

我们给出委托的定义,委托是为了降低一个对象的复杂度和耦合度,使其能够更具通用性将其中一些处理置于委托对象中的编码方式。通用类因为通用性即与具体应用的无关性而变为框架类,框架类保持委托对象的引用,并在特定时刻向委托对象发送消息。消息可能只是通知委托对象做一些事情,也可能是对委托对象进行控制。

实现原理

我们通过一个案例介绍委托设计模式实现原理和应用场景,重新绘制委托设计模式类图。

在古希腊有一个哲学家,他毕生只做三件事情:“睡觉”、“吃饭”和“工作”。为更好的生活,工作效率更高,他会找一个徒弟,把这些事情委托给徒弟做。然而要成为他的徒弟,需要实现一个协议,协议要求能够处理“睡觉”、“吃饭”和“工作”问题。三者之间的关系。

哲学家类图中,通用类(Philosopher)保持指向委托对象(ViewController)的“弱引用”(id<PhilosopherDelegate> delegate),委托对象(ViewController)就是哲学家的“徒弟”,他实现了协议PhilosopherDelegate,PhilosopherDelegate规定了3个方法:-(void) sleep、-(void) eat和-(void) work方法。

下面我们看看实现代码,委托协议PhilosopherDelegate.h代码如下:

[cpp] view plaincopy

1.  @protocol PhilosopherDelegate

2. 

3.  @required

4. 

5.  -(void) sleep;

6. 

7.  -(void) eat;

8. 

9.  -(void) work;

10.

11.@end

委托协议PhilosopherDelegate定义了3个方法,协议没有m文件,它的定义可以放在别的h文件中。它的实现类就是委托类ViewController的代码如下:

[cpp] view plaincopy

1.  //

2. 

3.  //  ViewController.h

4. 

5.  //

6. 

7.  @interface ViewController : UIViewController<PhilosopherDelegate>

8. 

9.  @end

10.

11.//

12.

13.//  ViewController.m

14.

15.//

16.

17.@implementation ViewController

18.

19.- (void)viewDidLoad

20.

21.{

22.

23.    [super viewDidLoad];

24.

25.    Philosopher *obj = [[Philosopher alloc ] init];

26.

27.    obj.delegate = self;

28.

29.    [obj start];

30.

31.}

32.

33.#pragma — PhilosopherDelegate 方法实现

34.

35.-(void) sleep

36.

37.{

38.

39.    NSLog(@”sleep…”);

40.

41.}

42.

43.-(void) eat

44.

45.{

46.

47.     NSLog(@”eat…”);

48.

49.}

50.

51.-(void) work

52.

53.{

54.

55.     NSLog(@”work…”);

56.

57.}

58.

59.@end


委托对象如何与通用类建立引用关系呢?我们通过viewDidLoad方法中的obj.delegate = self语句来指定委托对象和通用类间的引用关系。一般情况下通用类由框架直接提供,在这个例子中我们根据需要自己实现了通用类Philosopher,Philosopher.h的代码:

[cpp] view plaincopy

1.  //

2. 

3.  //  Philosopher.h

4. 

5.  //  DelegatePattern

6. 

7.  //

8. 

9.  #import “PhilosopherDelegate.h”

10.

11.@interface Philosopher : NSObject

12.

13.{

14.

15.    NSTimer *timer;

16.

17.    int count;

18.

19.}

20.

21.@property  (nonatomic, weak) id<PhilosopherDelegate> delegate;

22.

23.-(void) start;

24.

25.-(void) handle;

26.

27.@end

Philosopher.h中定义delegate属性,它的类型是id<PhilosopherDelegate>,它可以保存委托对象的引用,属性weak说明是“弱引用”。Philosopher.m文件代码如下:

[cpp] view plaincopy

1.  //

2. 

3.  // Philosopher.m

4. 

5.  //  DelegatePattern

6. 

7.  #import “Philosopher.h”

8. 

9.  @implementation Philosopher

10.

11.@synthesize delegate;

12.

13.-(void) start

14.

15.{

16.

17.    count= 0;

18.

19.    timer = [NSTimer scheduledTimerWithTimeInterval:3.0

20.

21.               target:self selector:@selector(handle)userInfo:nil repeats:YES];

22.

23.}

24.

25.-(void)handle

26.

27.{

28.

29.    switch (count)

30.

31.    {

32.

33.        case 0:

34.

35.            [self.delegate sleep];

36.

37.            count++;

38.

39.            break;

40.

41.        case 1:

42.

43.            [self.delegate eat];

44.

45.            count++;

46.

47.            break;

48.

49.        case 2:

50.

51.            [self.delegate work];

52.

53.            [timer  invalidate];

54.

55.            break;

56.

57.    }

58.

59.}

60.

61.@end

在本例中Philosopher模拟一些通用类发出调用,这个调用的发出是通过NSTimer每3秒发出一个,依次向委托对象发出消息sleep、eat和work。代码中self.delegate是指向委托对象ViewController的引用,[self.delegate
sleep]是调用ViewController中的sleep方法。

IOS常用设计模式之委托模式的更多相关文章

  1. iOS中常见的设计模式——单例模式\委托模式\观察者模式\MVC模式

    一.单例模式 1. 什么是单例模式? 在iOS应用的生命周期中,某个类只有一个实例. 2. 单例模式解决了什么问题? 想象一下,如果我们要读取文件配置信息,那么每次要读取,我们就要创建一个文件实例,然 ...

  2. PHP设计模式之委托模式

    委托模式: 通过分配或委托至其他对象,委托设计模式能够去除核心对象中的判决和复杂的功能性. class Bank{ protected $info; /* 设置基本信息 @param string $ ...

  3. 再起航,我的学习笔记之JavaScript设计模式28(委托模式)

    ## 委托模式 ### 概念介绍 **委托模式(Entrust): **多个对象接收并处理同一请求,他们将请求委托给另一个对象统一处理请求. ### 利用委托优化循环 如果我们有一个需求需要让用户点击 ...

  4. PHP设计模式系列 - 委托模式

    委托模式 通过分配或委托其他对象,委托设计模式能够去除核心对象中的判决和复杂的功能性. 应用场景 设计了一个cd类,类中有mp3播放模式,和mp4播放模式 改进前,使用cd类的播放模式,需要在实例化的 ...

  5. iOS常用设计模式——工厂方法(简单工厂模式,工厂方法模式, 抽象工厂模式)

    1. 简单工厂模式 如何理解简单工厂,工厂方法, 抽象工厂三种设计模式? 简单工厂方法包含:父类拥有共同基础接口,具体子类实现子类特殊功能,工厂类根据参数区分创建不同子类实例.该场景对应的UML图如下 ...

  6. iOS 设计模式-委托模式

    委托是指给一个对象提供机会对另一对象中的变化做出反应或者相应另一个对象的行为.其基本思想是协同解决问题. Delegate的使用场合 对象A内部发生了一些事情,想通知对象B 对象B想监听对象A内部发生 ...

  7. iOS常用设计模式和机制之代理

    Delegate : 1 代理设计模式的使用我们首先需要明白三个要素 *委托方:委托别人去执行某些操作的人(对象) *代理方:被委托区执行某些操作的人(对象) *协议:(protocol)委托方需要代 ...

  8. Java设计模式05:常用设计模式之原型模式(创建型模式)

    1. Java之原型模式(Prototype Pattern)     原型模式属于对象的创建模式.通过给出一个原型对象来指明所有创建的对象的类型,然后用复制这个原型对象的办法创建出更多同类型的对象. ...

  9. Java设计模式02:常用设计模式之工厂模式(创建型模式)

    一.工厂模式主要是为创建对象提供过渡接口,以便将创建对象的具体过程屏蔽隔离起来,达到提高灵活性的目的.  工厂模式在<Java与模式>中分为三类: 1)简单工厂模式(Simple Fact ...

随机推荐

  1. 根据选择项过滤GridView

    前台代码: <div> <asp:CheckBoxList ID="CheckBoxList1" runat="server" AutoPos ...

  2. 带参数的存储过程和标量Function

    在SQL Server中,我们通常会使用NEWID(),GETDATE(),等一些数据库函数,这些函数是很有帮助的,然后数据库也能够让我们自己写函数,即Function,下面简单说说Function的 ...

  3. CSS3 总结-2

    过渡属性 下面的表格列出了所有的转换属性: 属性 描述 CSS transition 简写属性,用于在一个属性中设置四个过渡属性. 3 transition-property 规定应用过渡的 CSS ...

  4. 门面(Facade)模式--医院,保安系统实例

    门面(Facade)模式 http://www.cnblogs.com/zhenyulu/articles/55992.html

  5. System.Web Namespce

    System.Web概述: System.Web是.NET中web应用开发的一个基础类库,定义浏览器与服务器之间的所有操作方法,包括请求输入流(HttpRequest).输出流(HttpRespons ...

  6. C语言之三大查找算法

    查找算法 1.二分查找 二分查找就是折半查找,其基本思想是:首先选取表中间位置的记录,将其关键字与给定关键字key进行比较,若相等,则查找成功.若key值比该关键字值大,则要找的元素一定在右子表中,则 ...

  7. CQRS架构设计及其实现

    CQRS架构设计及其实现 一.为什么要实践领域驱动? 近一年时间我一直在思考一个问题:“如何设计一个松耦合.高伸缩性.易于维护的架构?”.之所以有这样的想法是因为我接触的不少项目都是以数据库脚本来实现 ...

  8. HDU2084:数塔(DP)

    Problem Description 在讲述DP算法的时候,一个经典的例子就是数塔问题,它是这样描述的: 有如下所示的数塔,要求从顶层走到底层,若每一步只能走到相邻的结点,则经过的结点的数字之和最大 ...

  9. 2013杭州网络赛C题HDU 4640(模拟)

    The Donkey of Gui Zhou Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/O ...

  10. 小猪猪C++笔记基础篇(六)参数传递、函数重载、函数指针、调试帮助

    小猪猪C++笔记基础篇(六) ————参数传递.函数重载.函数指针.调试帮助 关键词:参数传递.函数重载.函数指针.调试帮助 因为一些事情以及自己的懒惰,大概有一个星期没有继续读书了,已经不行了,赶紧 ...