对于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. JS中onload的各种使用

    1.最简单的调用方式 直接写到html的body标签里面,如: <html> <body onload="func()"> </body> &l ...

  2. js字符串大小写转换

    var str = 'hello world'; alert(str.toUpperCase());//将字符串转换为大写. alert(str.toLowerCase());//将字符串转换为小写. ...

  3. 使用wget -i下载多个文件

    使用wget -i下载多个文件 命令: wget -i filelist.txt 说明: 首先,保存一份下载链接文件 cat > filelist.txt url1 url2 url3 url4

  4. 升级到iis7 的web.config配置

    经典模式或集成模式都识别system.webServers节点 aspnet的isapi分32位和64位 不存在时会报404或403

  5. Android 的平台碎片化问题

    Android 的平台碎片化问题 看到篇不错的文章,转载过来. -------------------------------------- 与iOS开发相比,Android开发平添了不小的工作量,因 ...

  6. cmake学习笔记(五)

    在cmake 学习笔记(三) 中简单学习了 find_package 的 model 模式,在cmake 学习笔记(四)中了解一个CMakeCache相关的东西.但靠这些知识还是不能看懂PySide使 ...

  7. java学习之二叉树的实现

    二叉树是一种数据结构,每个节点都有两个子节点. 二叉树的遍历有三种方式, 先序遍历是 根节点,左子树,右子树: 中序遍历是 左子树,根节点,右子树: 后序遍历是 左子树,右子树,根节点: java实现 ...

  8. 第一种:NStread

    - (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view, typica ...

  9. js获取控件位置

    //获取坐标位置 function getpos(e) { var t=e.offsetTop; var l=e.offsetLeft; var height=e.offsetHeight; whil ...

  10. hdu1533解题报告

    题意:这里有一个N*M的方格图.....图中m代表人,H代表房子...并且人数和房子的数量是相等的..那么.每个人可以竖直或者横向走一格,并且花费1S元...那么为了让所有的人进入房子,求解最小的花费 ...