软件开发常用设计模式—iOS 中的代理模式总结

比如现在有一个人,想要买一张电影票,但是她很忙碌,没时间去买,那怎么办呢?只能说委托给另一个人去买。

此时,需要 person 给 other 发送消息,通知 other 去给她买电影票,而 other 也要反馈消息给 person,此时 other 就是一个代理人,person 委托代理人去办事情(买票)。代理人是给委托人代办一些事情的人。具体代理人怎么做的这些事情,委托人不管,委托人只看反馈。

先看代理设计模式的基本原理

#import <Foundation/Foundation.h>
#import "Agent.h"

@interface Person : NSObject

- (void) buyTicket;

// 拥有一个代理属性
@property (nonatomic, retain) Agent delegate;

@end

一个委托人的类,person 类和 person 类的实现

#import "Person.h"

@implementation Person

// 买电影票
- (void)buyTicket
{
    // 叫代理去帮自己买票(询问一下票价、询问一下票的剩余张数)
    double price = [_delegate ticketPrice];
    int number =  [_delegate leftTicketsNumber];

    NSLog(@"通过代理的帮忙,票价=%f,还剩%d张票", price, number);
}

- (void)dealloc
{
    [_delegate release];
    [super dealloc];
}
@end

其中,委托人不亲自去买票,而是让代理人去买票,而具体代理人怎么去办事,委托人不去关心。只需要在委托类里去调对应的代理实现的方法即可。

下面是代理类的实现,其中有代理代办的事情,需要查询剩余票数,和询问票价单价。这些都不需要委托人去做,而是代理给一一代办。

#import "Agent.h"

@implementation Agent

// 剩余的票数
- (int)leftTicketsNumber
{
    // ... 亲自跑电影院\或者打电话

    return 1;
}

// 每一张票多少钱
- (double)ticketPrice
{
    // ... 亲自跑电影院\或者打电话
    return 1000;
}
@end

在主方法里,委托人对象 p,p 想去买电影票,但是没时间买,那么好了,让代理去代办这个事情吧,具体怎么办,不管他,只要能买回票就行。然后代理对象 a 。接下来,把代理对象 a 赋值给委托对象 p 的_delegate 成员。然后开始调用买票的方法。

#import <Foundation/Foundation.h>
#import "Person.h"
#import "Agent.h"

int main(int argc, const char * argv[])
{

    @autoreleasepool {
        Person *p = [[Person alloc] init];

        Agent *a = [[Agent alloc] init];

        p.delegate = a;

        [p buyTicket];
    }

    return 0;
}

这样基本上实现了代理设计模式的思路,需要一个委托类的对象p,一个代理类的对象 a,在委托类里声明了代理类的对象delegate,然后把代理类的对象 a 传入委托类 b 中的 delegate,最后让p 给 a 发送消息,本质也就是让 p去调用 a 的方法(使用 p 内的 delegate 调用的 a 的方法)去执行 p 本来想执行的事务。但是,这样的写法,非常不规范,不符合低耦合高内聚的原则!继续分析:

比如,我们把 Agent 类删掉或者哪怕换个名字,那么以后在使用这个代理模式,Person 类就无法发挥作用,就失去了代理设计模式的功能,如果非要用,就需要改变这个架构的代码,尤其是不仅仅需要改变代理类的代码,麻烦的是每次还要修改委托类的代码。这样的话麻烦很大!因为,person类直接依赖了 agent 类。这会使得程序变得耦合度很高!

需要改进代理设计模式:

1、类名不能写死!iOS 中需要使用 id类型(万能指针)代替类类型

2、联想 oc 中的协议语法,需要定义一个协议。因为如果 person 仅仅满足 id 类型,但是不能保证程序知道这个对象里面有什么方法或者属性,那么可以使用协议,只要满足这个协议,那么就可以做我的代理。

3、这样搞,完全是低耦合的设计。要求换代理的时候,仅仅需要增加新的代理累即可,或者删除代理的时候,删除即可。而每次的委托类的代码无需做出任何改变即可满足。

如图所示,代理在给人办事情的时候,不是说,想办就可以办,或者说谁想来都能办的,必须要遵循一份我们提供的协议!因为,不遵循协议,鬼知道代理里面有什么方法或者属性呢?你能办什么事情,人都不知道!故必须遵循一份提供的协议,告诉人,代理可以做什么,具体怎么去做,那都是代理的事情了。人不用关心过程,只看结果,事情是办了,还是没办。而人的内部,为了低耦合的实现,把 agent 类型的对象,换成 id 类型,然后让它遵循协议即可。这样就实现了低耦合!代码如下:

#import <Foundation/Foundation.h>
#import "TicketDelegate.h"

@interface Person : NSObject

- (void) buyTicket;

// 拥有一个代理属性
// id代表代理的类名随便
// 但必须遵守TicketDelegate协议
@property (nonatomic, retain) id<TicketDelegate> delegate;

@end

下面是person 的 m 文件

#import "Person.h"

@implementation Person

// 买电影票
- (void)buyTicket
{
    // 叫代理去帮自己买票(询问一下票价、询问一下票的剩余张数)
    double price = [_delegate ticketPrice];
    int number =  [_delegate leftTicketsNumber];

    NSLog(@"通过代理的帮忙,票价=%f,还剩%d张票", price, number);
}

- (void)dealloc
{
    [_delegate release];
    [super dealloc];
}
@end

下面是协议的代码,只需要声明一些方法即可。

#import <Foundation/Foundation.h>

// 声明一些方法
@protocol TicketDelegate <NSObject>

// 返回票价
- (double) ticketPrice;

// 还剩多少张票
- (int) leftTicketsNumber;

@end

下面增加一个新的代理类 nextagent,这个代理类,需要遵守这份委托人提供的协议。

#import <Foundation/Foundation.h>
#import "TicketDelegate.h"

@interface NextAgent : NSObject<TicketDelegate>

@end

新代理的实现。

#import "NextAgent.h"

@implementation NextAgent

- (double)ticketPrice
{
    return 500;
}

- (int)leftTicketsNumber
{
    return  10;
}

@end

在 iOS 中的实际应用很多地方都使用了代理设计模式

比如 qq 聊天的表格,是一行行的,或者淘宝客户端展示产品的列表。如下 qq 聊天列表,左边一个头像,右边一般是两行,第一行是昵称,第二行是最近的一段聊天记录显示。

整个的屏幕的表格是table,table 里面很多的行,显式的很多行的数据,table 本身不去做这些事情,而是表格控件去做—UITableView很常用的控件,这个控件里面有个 id 类型的数据源 datasource,也就是任何人都能做它的数据元,,但是前提是必须遵守一份它规定的协议——UITableViewDataSource 协议,里面很多方法。这就是代理设计模式的使用。

时间: 2024-08-04 02:56:48

软件开发常用设计模式—iOS 中的代理模式总结的相关文章

软件开发常用设计模式—门面模式总结

facade 门面模式定义:有的人也叫它外观模式 为子系统中的一组接口提供一个一致的界面,此模式定义了一个高层接口,这个接口使得这个子系统更加容易使用. 模式说明: 子系统(SubSystem):负责处理复杂的逻辑处理.不直接跟客户打交道.门面(Facade):负责跟子系统进行交互,提供简单易用的功能或接口给客户.客户(Client):通过门面和子系统进行交互,不需关心子系统的细节. 主要作用: 简化复杂接口, 解耦和来屏蔽客户端对子系统的直接访问 c++实现代码(网上大牛提供) 1 #incl

软件开发常用设计模式—单例模式总结

单例模式:就是只有一个实例. singleton pattern单例模式:确保某一个类在程序运行中只能生成一个实例,并提供一个访问它的全局访问点.这个类称为单例类.如一个工程中,数据库访问对象只有一个,电脑的鼠标只能连接一个,操作系统只能有一个窗口管理器等,这时可以考虑使用单例模式. 众所周知,c++中,类对象被创建时,编译系统为对象分配内存空间,并自动调用构造函数,由构造函数完成成员的初始化工作,也就是说使用构造函数来初始化对象. 1.那么我们需要把构造函数设置为私有的 private,这样可

IOS开发常用设计模式

IOS开发常用设计模式 说起设计模式,感觉自己把握不了笔头,所以单拿出iOS开发中的几种常用设计模式谈一下. 单例模式(Singleton) 概念:整个应用或系统只能有该类的一个实例 在iOS开发我们经常碰到只需要某类一个实例的情况,最常见的莫过于对硬件参数的访问类,比如UIAccelerometer.这个类可以帮助我们获得硬件在各个方向轴上的加速度,但是我们仅仅需要它的一个实例就够了,再多,只会浪费内存. 所以苹果提供了一个UIAccelerometer的实例化方法+sharedAcceler

【开发记录】iOS中使用 Reachability 检测网络

如果你想在iOS程序中提供一仅在wifi网络下使用(Reeder),或者在没有网络状态下提供离线模式(Evernote).那么你会使用到Reachability来实现网络检测. 写本文的目的 了解Reachability都能做什么 检测3中网络环境 2G/3G wifi 无网络 如何使用通知 单个controller 多个controller 简单的功能: 仅在wifi下使用 Reachability简介 Reachablity 是一个iOS下检测,iOS设备网络环境用的库. 监视目标网络是否可

C#设计模式之十二代理模式(Proxy Pattern)【结构型】

原文:C#设计模式之十二代理模式(Proxy Pattern)[结构型] 一.引言 今天我们要讲[结构型]设计模式的第七个模式,也是"结构型"设计模式中的最后一个模式,该模式是[代理模式],英文名称是:Proxy Pattern.还是老套路,先从名字上来看看."代理"可以理解为"代替",代替"主人"做一些事情,为什么需要"代理",是因为某些原因(比如:安全方面的原因),不想让"主人"直接

【转】设计模式(十一)代理模式Proxy(结构型)

设计模式(十一)代理模式Proxy(结构型) 1.概述 因为某个对象消耗太多资源,而且你的代码并不是每个逻辑路径都需要此对象, 你曾有过延迟创建对象的想法吗 ( if和else就是不同的两条逻辑路径) ? 你有想过限制访问某个对象,也就是说,提供一组方法给普通用户,特别方法给管理员用户?以上两种需求都非常类似,并且都需要解决一个更大的问题:你如何提供一致的接口给某个对象让它可以改变其内部功能,或者是从来不存在的功能? 可以通过引入一个新的对象,来实现对真实对象的操作或者将新的对象作为真实对象的一

OC中的代理模式

OC中的代理模式,关于代理模式,如果还有同学不太清楚的话,就自己去补充知识了,这里就不做介绍了,这里只介绍OC中是如何实现代理模式的.这里举一个简单的例子:小孩类,护士类,保姆类,其中小孩类有两个方法:wash和play这里代理对象就是:护士类.保姆类,小孩类是被代理对象.看一下代码:首先看一下小孩类:Children.h[objc]  view plaincopy 1. //   2. //  Children.h   3. //  12_DesignStyle   4. //   5. //

重温设计模式(一)—代理模式

通过这次设计模式的交流,发现无论是技术上还是思想上需要提升的空间还有很多.收获比预期的要多的多.给我触动最深的就是以下几点: 1. 面向对象的精华:抽象.封装.继承.多态 2.设计模式六大原则的运用:单一职责.开闭原则.合成聚合.依赖倒装.里氏代换.迪米特 3.让自己思绪飞翔-大胆的去想象,只有去想了.做了,你才知道最后的结果 初次学习代理模式的博文:http://blog.csdn.net/gxq741718618/article/details/8781099 下面用另外一种愉快的心情了解一

Objective-C中的委托(代理)模式

我个人更喜欢把委托(Delegate)模式称为代理(Proxy)模式.还是那句话,第一次接触代理模式是在Java中接触的,在Java中实现代理模式和接口是少不了的.当时学习Spring的时候用到了接口回调,其实就是实现的委托代理模式.简单的说代理就是把相应的功能交给实现接口的相应的类中来解决.在OC中没有接口该如何实现代理呢?前面的博客中笔者说提了一句,在OC中的协议和Java中的接口极为相似,都是只声明方法而不去实现,方法的实现在OC中交个遵循协议的类,而在Java中方法的实现交给实现接口的类