对于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. iOS系统原生二维码条形码扫描

    本文讲述如何用系统自带的东东实现二维码扫描的功能:点击当前页面的某个按钮,创建扫描VIEW.细心的小伙伴可以发现 title被改变了,返回按钮被隐藏了.这个代码自己写就行了,与本文关系不大...绿色的 ...

  2. Java学习03

    Java学习03 1.java面试一些问题 一.什么是变量 变量是指在程序执行期间可变的数据.类中的变量是用来表示累的属性的,在编程过程中,可以对变量的值进行修改.变量通常是可变的,即值是变化的 二. ...

  3. JDBC_获取数据库连接

    <span style="font-size:24px;">package src.com.jdbc.java; import java.io.IOException; ...

  4. KVM镜像管理利器-guestfish使用详解

    原文  http://xiaoli110.blog.51cto.com/1724/1568307   KVM镜像管理利器-guestfish使用详解 本文介绍以下内容: 1. 虚拟机镜像挂载及w2k8 ...

  5. Nginx Rewrite规则初探(转)

    Nginx  rewrite(nginx url地址重写)Rewrite 主要的功能就是实现URL的重写,Nginx的Rewrite规则采用Pcre,perl兼容正则表达式的语法规则匹配,如果需要Ng ...

  6. asp.net从客户端检测到有潜在危险的Request.Form 值

    asp.net开发中,经常遇到“从客户端检测到有潜在危险的Request.Form 值”错误提示,很多人给出的解决方案是: 1.web.config文档<system.web>后面加入这一 ...

  7. Swift - 2 (?和!、结构体、类、协议、扩展、闭包)

    1> 可选类型(?)和强制解包(!) 在swift中,可选类型(?) 其根源是一个 枚举型,里面有 None 和 Some 两种类型.其实所谓的 nil 就是 Optional.None , 非 ...

  8. 1369 - Answering Queries(规律)

    1369 - Answering Queries   PDF (English) Statistics Forum Time Limit: 3 second(s) Memory Limit: 32 M ...

  9. 【解决ViewPager在大屏上滑动不流畅】 设置ViewPager滑动翻页距离

    在项目中做了一个ViewPager+Fragment滑动翻页的效果,在模拟器和小米手机上测试也比较正常.但是换到4.7以上屏幕测试的时候发现老是滑动失效. 因为系统默认的滑动策略是当用户滑动超过半屏之 ...

  10. 【第三方SDK】百度地图实现最简单的定位功能(无地图界面)

    在近期的项目中,须要实现无地图界面的定位功能,定位用户所在的城市.因此,本篇文章,主要介绍怎样使用百度地图SDK实现无导航界面的定位功能. 1.申请百度开发人员账户 2.创建应用,获取key 例如以下 ...