设计模式——代理模式
代理模式(Proxy Pattern)是一个使用率非常高的模式。
定义: Provide a surrogate or placeholder for another object to control access to it. (为其对象提供一种代理以控制这个对象的访问)
代理模式也叫委托模式,它是一项基本的设计技巧。许多其他的模式,如状态模式、策略模式、访问者模式本质上是在更特殊的场合采用了委托模式,而且在日常应用中,代理模式可以提供非常好的访问控制。
三个角色的定义
抽象主题类可以是抽象类也可以是接口,是一个最普通的业务类型定义,无特殊要求。
也叫做被委托的角色、被代理的角色。是业务逻辑的具体执行者。
也叫委托类、代理类。它负责对真实角色的应用,把所以抽象主题定义的方法限制委托给真实主题角色实现,并且在真实主题角色处理完毕前后做预处理和善后工作。
一个代理类可以代理多个被委托者或者被代理者,因此一个代理者具体代理哪个真实主题角色,是由场景类决定的。在通常情况下,一个接口只需要一个代理类就可以了,具体代理哪个实现类由高层模块决定,也就是在代理类的构造函数中传递被代理者。
类似现实生活中买房子的中介,打官司的律师。你不想参与中间过程的是是非非。减轻用户的负担。代理模式使用场景非常多。最典型的是Spring AOP中的动态代理。
普通代理就是我们要知道代理的存在,也就是类似GamePlayerProxy这个代理类的存在,然后才能访问。
普通代理的要求就是客户端只能访问代理角色,而不能访问真实角色。以游戏代练为例子,
GamePlayer的构造函数增加了_gamePlayer参数,而代理角色则只要传入代理者名字即可,而不需要说是替哪个对象做代理
在构造函数中,传来进来一个IGaemPlayer对象,检查谁能创建真实的角色,或者做出别的限制。
仅仅修改了构造函数,传递进来一个代理者名称,即可进行代理,在这种改造下,系统更加简洁,调用者只知道代理的存在就行,不用知道代理了谁。
在该模式下,调用者只知道代理而不知道真实的角色是谁,屏蔽了真实角色的变更对高层模块的影响,真实的主题角色想怎么修改都可以,对高层次的模块没有任何的影响,只要你实现了接口所对应的方法,该模式非常适合对扩展性要求较高的场合。
强制代理是要“强制”,必须通过真实角色查找到代理角色,否则不能进行访问。无论是通过代理类还是直接new一个主题角色类,都不能访问,只有通过真实角色指定的代理类才能访问,也就是说由真实的角色管理代理角色。例如你和一个明星比较熟,你直接找明星帮忙要见导演,但是明星说她比较忙,让你找她的经纪人。你本来想绕过她的代理,谁知道她返回的还是她的代理,这就是强制代理。你可以不知道代理的存在,但是你的所作所为还是需要代理为你提供服务。
强制代理的概念就是要从真实的角色查找到代理角色,不允许直接访问真实角色。高层模块只要调用 getProxy() 就可以访问真实角色的所以方法,它根本不需要产生一个代理出来,代理的管理已经由真实角色自己完成。
一个类可以实现多个接口,完成不同任务的整合。也就是说代理类不仅仅可以实现主题接口,也可以实现其他接口完成不同的任务,而且代理的目的是在目标对象方法的基础上作增强,这种增强的本质通常就是对目标对象的方法进行拦截合过滤。
动态代理
在招募平台发布招募信息即可。
招募美术设计代理商需要发布招募信息,留下联系方式。
代理商又称商务代理,是在其行业管理范围内接受他人委托,为他人促成或缔结交易的一般代理人。代理商是代企业打理生意,是厂家给予商家佣金额度的一种经营行为。所代理货物的所有权属于厂家,而不是商家。因为商家不是售卖自己的产品,而是代企业转手卖出去。
广告代理:指广告经营者接受广告主或广告发布者委托,从事的广告市场调查、广告信息咨询、企业形象策划、广告战略策划、广告媒介安排等经营活动。
广告就是宣传方式,主要的宣传内容是产品、服务内容、文化体育娱乐节目等。主要的宣传途径是电视、广播、网络、报刊、招贴等。广告在现代企业公司销售产品不可或缺的一种方式。
1、代理业
代理业,是指代委托人办理受托事项的业务,包括代购代销货物、代办进出口、介绍服务、其他代理服务.
1) 代购代销货物,是指受托购买货物或销售货物,按实购或实销额进行结算并收取手续费的业务.
2) 代办进出口,是指受托办理商品或劳务进出口的业务.
3) 介绍服务,是指中介人介绍双方商谈交易或其他事项的业务.
4) 其他代理服务,是指受托办理上列事项以外的其他事项的业务.
5) 金融经纪业、邮政部门的报刊发行业务,不按本税目征税.
2、旅店业
旅店业,是指提供住宿服务的业务.
3、饮食业
饮食业,是指通过同时提供饮食和饮食场所的方式为顾客提供饮食消费服务的业务. 饭馆、餐厅及其他饮食服务场所,为顾客在就餐的同时进行的自娱自乐形式的歌舞活动所提供的服务,按"娱乐业"税目征税.
4、旅游业
旅游业,是指为旅游者安排食宿、交通工具和提供导游等旅游服务的业务.
5、仓储业
仓储业,是指利用仓库、货场或其他场所代客贮放、保管货物的业务.
6、租赁业
租赁业,是指在约定的时间内将场地、房屋、物品、设备或设施等转让他人使用的业务. 按照联合国和世界贸易组织的分类方法,服务业主要包括11大类:
商务服务(其中又分为专业服务、计算机服务、干租服务等类别)通讯服务(其中又分为邮政服务、速递服务、电信服务、视听服务等类别)建筑和相关工程服务分销服务(其中又分为佣金代理服务、批发服务、零售服务、特许经营服务等类别)
教育服务环境服务金融服务(其中又分为保险和保险相关服务、银行和其他金融服务、证券服务等类别)与健康相关的服务和社会服务旅游和与旅行相关的服务娱乐、文化和体育服务
运输服务(其中又分为海运服务、内河运输服务、航空运输服务、航天运输服务、铁路运输服务、公路运输服务、管道运输服务、运输辅助服务等类型). 服务业从为流通服务到为生活服务,进一步扩展到为生产服务,经历了一个很长的历史过程.
服务业的社会性质也随着历史的发展而变化.在前资本主义社会,主要是为奴隶主和封建主服务,大多由小生产者经营,因而具有小商品经济性质.资本主义服务业以盈利为目的,资本家和服务劳动者之间的关系是雇佣关系.
社会主义服务业是以生产资料公有制为基础,以提高人民群众物质文化生活为目的,是真正为全社会的生产、流通和消费服务的行业,
7、广告业
各地的广告业发票样子不同.既有手写的也有机打的,一般都有水印,个别地方是没有水印的.
目前重庆地税监制的广告业发票有电脑版和手工填开版两种.山西省广告业务应使用服务业发票.
登录接口ILogin 验证登录 只有登陆后才能执行该方法
创建MyInvocationHandler 来监听代理类 方法的执行
在测试的activity中 使用:
app gradle 配置
在 project gradle
Login
LoginAspect
使用
协议:用来指定代理双方可以做什么,必须做什么。
委托对象:根据指定的协议,指定代理去完成什么功能。
代理对象:根据指定的协议,完成委托方需要实现的功能。
从上图中可以看到三方之间的关系,在实际应用中通过协议来规定代理双方的行为,协议中的内容一般都是方法列表,当然也可以定义属性。
协议是公共的定义,如果只是某个类使用,我们常做的就是写在某个类中。如果是多个类都是用同一个协议,建议创建一个Protocol文件,在这个文件中定义协议。遵循的协议可以被继承,例如我们常用的 UITableView ,由于继承自 UIScrollView 的缘故,所以也将 UIScrollViewDelegate 继承了过来,我们可以通过代理方法获取 UITableView 偏移量等状态参数。
协议只能定义公用的一套接口,类似于一个约束代理双方的作用。但不能提供具体的实现方法,实现方法需要代理对象去实现。协议可以继承其他协议,并且可以继承多个协议,在iOS中对象是不支持多继承的,而协议可以多继承。
协议有两个修饰符 @optional 和 @required ,创建一个协议如果没有声明,默认是 @required 状态的。这两个修饰符只是约定代理是否强制需要遵守协议,如果 @required 状态的方法代理没有遵守,会报一个黄色的警告,只是起一个约束的作用,没有其他功能。
无论是 @optional 还是 @required ,在委托方调用代理方法时都需要做一个判断,判断代理是否实现当前方法,否则会导致崩溃。
在iOS中代理的本质就是代理对象内存的传递和操作,我们在委托类设置代理对象后,实际上只是用一个id类型的指针将代理对象进行了一个弱引用。委托方让代理方执行操作,实际上是在委托类中向这个id类型指针指向的对象发送消息,而这个id类型指针指向的对象,就是代理对象。
通过上面这张图我们发现,其实委托方的代理属性本质上就是代理对象自身,设置委托代理就是代理属性指针指向代理对象,相当于代理对象只是在委托方中调用自己的方法,如果方法没有实现就会导致崩溃。从崩溃的信息上来看,就可以看出来是代理方没有实现协议中的方法导致的崩溃。
而协议只是一种语法,是声明委托方中的代理属性可以调用协议中声明的方法,而协议中方法的实现还是有代理方完成,而协议方和委托方都不知道代理方有没有完成,也不需要知道怎么完成。
由于代理对象使用强引用指针,引用创建的委托方对象,并且成为委托对象的代理。这就会导致委托对象的delegate属性强引用代理对象,导致循环引用的问题,最终两个对象都无法正常释放。
我们将委托对象的delegate属性,设置为弱引用属性。
weak 和 assign 是一种“非拥有关系”的指针,通过这两种修饰符修饰的指针变量,都不会改变被引用对象的引用计数。但是在一个对象被释放后, weak 会自动将指针指向 nil ,而 assign 则不会。在iOS中,向 nil 发送消息时不会导致崩溃的,所以 assign 就会导致野指针的错误 unrecognized selector sent to instance 。
所以我们如果修饰代理属性,还是用 weak 修饰,比较安全。