• IOS常用设计模式之委托模式


    对于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)就是哲学家的徒弟,他实现了协议PhilosopherDelegatePhilosopherDelegate规定了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语句来指定委托对象和通用类间的引用关系。一般情况下通用类由框架直接提供,在这个例子中我们根据需要自己实现了通用类PhilosopherPhilosopher.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模拟一些通用类发出调用,这个调用的发出是通过NSTimer3秒发出一个,依次向委托对象发出消息sleepeatwork。代码中self.delegate是指向委托对象ViewController的引用,[self.delegate sleep]是调用ViewController中的sleep方法。

     

  • 相关阅读:
    javascript--Date
    PL/SQL的命令行窗口中执行脚本
    关于资产新增接口问题描述
    ORA-00600: internal error code, arguments: [kqludp2], [0x08D226918], [0], [], [], [], [], [], [], [], [], []
    Oracle 表空间扩容
    EBS 创建会计科目 小结
    EBS AP 创建会计科目失败
    EBS GL 日记账行“账户说明”段说明显示不全
    EBS 修改系统名称
    EBS 修改系统颜色
  • 原文地址:https://www.cnblogs.com/yangmx/p/3634840.html
Copyright © 2020-2023  润新知