对于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. HDU4712+随机算法

    随机算法 求n个20位的2进制串的MinDist. Dist:两个串的异或结果中1的个数 /* 随机算法 */ #include<algorithm> #include<iostre ...

  2. 悬浮二维码 QQ ToTop

    //回顶部 <div id="lqdbe" style="position: absolute; visibility: visible; z-index: 1;  ...

  3. C#中类的运用(Eighth day)

    又到了总结知识的时刻了,今天在云和学院学习了类的运用,下面是今天所学知识的总结: 理论: 类的定义语法: [访问修饰符] class 类名 { 成员;  // 1.通过字段来描述类别信息的变量 ... ...

  4. Task线程 同时执行多个任务

    Task taskTest = Task.Factory.StartNew(() => { Console.WriteLine("); },TaskCreationOptions.No ...

  5. C - N皇后问题(搜索)

    Description 在N*N的方格棋盘放置了N个皇后,使得它们不相互攻击(即任意2个皇后不允许处在同一排,同一列,也不允许处在与棋盘边框成45角的斜线上. 你的任务是,对于给定的N,求出有多少种合 ...

  6. URAL 1225 Flags

    题目:click here #include <bits/stdc++.h> using namespace std; typedef long long ll; ; int n; ll ...

  7. 裸机代码(uboot) : clear bss

    一. bss介绍: 代码中函数.变量.常量 / bss段.data段.text段 /sct文件..map文件的关系[实例分析arm代码(mdk)] bss和data的区别: 全局的未初始化变量存在于. ...

  8. json对象的操作,json工具

    项目中经常用到json,现在把写了几个js函数,用来获取json对象或者json字符串的长度,以及获取其的key值,value值,并且返回. 这样以后可以直接拿来用,可以省去不少麻烦,也方便以后查看. ...

  9. Laravel 5.1 ACL权限控制 二 之策略类

    随着应用逻辑越来越复杂,要处理的权限越来越多,将所有权限定义在AuthServiceProvider显然不是一个明智的做法,因此Laravel引入了策略类,策略类是一些原生的PHP类,和控制器基于资源 ...

  10. Python网络编程——获取远程设备的IP地址

    有时需要把设备的主机名转换成对应的IP地址,下面是一个简单的操作. import socket def get_remote_machine_info(): # 定义get_remote_machin ...