首页 / 设计模式 / 设计模式之代理模式20170724
设计模式之代理模式20170724
内容导读
互联网集市收集整理的这篇技术教程文章主要介绍了设计模式之代理模式20170724,小编现在分享给大家,供广大互联网技能从业者学习和参考。文章包含10929字,纯文字阅读大概需要16分钟。
内容图文
结构型设计模式之代理模式:
一、含义
代理模式也叫做委托模式,其定义如下:
为其他对象提供一种代理以控制对这个对象的访问。
二、代码说明
1.主要有两个角色
1)具体主题角色
也叫做委托角色、被代理角色。它是业务逻辑的具体执行者。
2)代理主题角色
也叫做委托类、代理类。它负责对真实角色的应用,把所有抽象主题类定义的方法限制委托给真实主题角色实现,并且在真实主题角色处理完毕前后做预处理和善后处理工作。
一个代理类可以代理多个被委托者或被代理者。
2.在用C实现过程中也是参考这种思想,以游戏代理场景举例,具体实现如下:
1)代理模式使用场景:
1 /* **************************************************************************** 2 * Copyright (C) 2017-2018 Hanson Yu All rights reserved. 3 ------------------------------------------------------------------------------ 4 * File Module : ProxyPatternUsage.c 5 * Description : 代理模式的使用 6 7 book@book-desktop:/work/projects/test/DesignPatterns/ProxyPattern$ gcc -o ProxyPatternUsage GamePlayer.c ProxyPattern.c ProxyPatternUsage.c 8 book@book-desktop:/work/projects/test/DesignPatterns/ProxyPattern$ ./ProxyPatternUsage 9 -----------------开始打游戏---------------- 10 登录名为ZhangSan的用户:张三,登录成功! 11 张三 在打怪! 12 张三又升了一级! 13 14 * Created : 2017.07.21. 15 * Author : Yu Weifeng 16 * Function List : 17 * Last Modified : 18 * History : 19 ***************************************************************************** */ 20 #include"stdio.h"21 #include"malloc.h"22 #include"stdlib.h"23 #include"string.h"24 #include"ProxyPattern.h"2526272829/***************************************************************************** 30-Fuction : main 31-Description : 32-Input : 33-Output : 34-Return : 35* Modify Date Version Author Modification 36* ----------------------------------------------- 37* 2017/07/19 V1.0.0 Yu Weifeng Created 38******************************************************************************/39int main(int argc,char **argv) 40{ 41 g_tGamePlayer.SetName("张三");//设置玩家42 g_tGamePlayerProxy.SetGamePlayer(g_tGamePlayer.tIGamePlayer);//设置代理者(表示代理谁)4344 printf("-----------------开始打游戏----------------\r\n"); 45 g_tGamePlayerProxy.tIGamePlayer.Login("ZhangSan","Password"); 46 g_tGamePlayerProxy.tIGamePlayer.KillBoss(); 47 g_tGamePlayerProxy.tIGamePlayer.Upgrade(); 4849return0; 50 }
2)被调用者:
1 /* **************************************************************************** 2 * Copyright (C) 2017-2018 Hanson Yu All rights reserved. 3 ------------------------------------------------------------------------------ 4 * File Module : ProxyPattern.c 5 * Description : 代理模式 6 本文件是代理角色 7 以游戏代理举例 8 9 * Created : 2017.07.21. 10 * Author : Yu Weifeng 11 * Function List : 12 * Last Modified : 13 * History : 14 ***************************************************************************** */ 15 #include"stdio.h"16 #include"malloc.h"17 #include"stdlib.h"18 #include"string.h"19 #include"ProxyPattern.h"2021staticvoid SetGamePlayer(T_IGamePlayer i_tGamePlayer); 22staticvoid ProxyLogin(char *i_strUserName,char *i_strPassword); 23staticvoid ProxyKillBoss(); 24staticvoid ProxyUpgrade(); 2526static T_IGamePlayer g_tIGamePlayer; 2728const T_GamePlayerProxy g_tGamePlayerProxy={ 29 .SetGamePlayer =SetGamePlayer, 30 .tIGamePlayer ={ProxyLogin,ProxyKillBoss,ProxyUpgrade}, 31}; 32/***************************************************************************** 33-Fuction : SetGamePlayer 34-Description : 公有函数 35-Input : 36-Output : 37-Return : 38* Modify Date Version Author Modification 39* ----------------------------------------------- 40* 2017/07/21 V1.0.0 Yu Weifeng Created 41******************************************************************************/42staticvoid SetGamePlayer(T_IGamePlayer i_tGamePlayer) 43 {//具体T_GamePlayer为只读,所以不能传址,使用传值形式,即拷贝了副本44 memcpy(&g_tIGamePlayer,&i_tGamePlayer,sizeof(T_IGamePlayer));//这里就可以取址了45} 4647/***************************************************************************** 48-Fuction : ProxyLogin 49-Description : 公有函数 50-Input : 51-Output : 52-Return : 53* Modify Date Version Author Modification 54* ----------------------------------------------- 55* 2017/07/21 V1.0.0 Yu Weifeng Created 56******************************************************************************/57staticvoid ProxyLogin(char *i_strUserName,char *i_strPassword) 58{ 59 g_tIGamePlayer.Login(i_strUserName,i_strPassword); 60} 6162/***************************************************************************** 63-Fuction : ProxyKillBoss 64-Description : 公有函数 65-Input : 66-Output : 67-Return : 68* Modify Date Version Author Modification 69* ----------------------------------------------- 70* 2017/07/21 V1.0.0 Yu Weifeng Created 71******************************************************************************/72staticvoid ProxyKillBoss() 73{ 74 g_tIGamePlayer.KillBoss(); 75} 7677/***************************************************************************** 78-Fuction : ProxyUpgrade 79-Description : 公有函数 80-Input : 81-Output : 82-Return : 83* Modify Date Version Author Modification 84* ----------------------------------------------- 85* 2017/07/21 V1.0.0 Yu Weifeng Created 86******************************************************************************/87staticvoid ProxyUpgrade() 88{ 89 g_tIGamePlayer.Upgrade(); 90 }
1 /* **************************************************************************** 2 * Copyright (C) 2017-2018 Hanson Yu All rights reserved. 3 ------------------------------------------------------------------------------ 4 * File Module : ProxyPattern.h 5 * Description : 代理模式 6 7 * Created : 2017.07.21. 8 * Author : Yu Weifeng 9 * Function List : 10 * Last Modified : 11 * History : 12 ***************************************************************************** */ 13 #ifndef PROXY_PATTERN_H 14 #define PROXY_PATTERN_H 151617 typedef struct IGamePlayer 18{ 19void (*Login)(char *i_strUserName,char *i_strPassword); 20void (*KillBoss)(); 21void (*Upgrade)(); 22}T_IGamePlayer; 2324 typedef struct GamePlayer 25{ 26 T_IGamePlayer tIGamePlayer;//实现同一个接口27void (*SetName)(char *i_strName);//私有变量放内部不放外部的原因是 28//放外部,则要修改接口,29}T_GamePlayer; 3031 typedef struct GamePlayerProxy 32{ 33 T_IGamePlayer tIGamePlayer;//实现同一个接口34void (*SetGamePlayer)(T_IGamePlayer i_tGamePlayer);//私有变量放内部不放外部的原因是 35//放外部,则要修改接口,导致接口内方法参数增加以及变得复杂36}T_GamePlayerProxy; 373839const T_GamePlayerProxy g_tGamePlayerProxy;//私有变量放内部,单例模式 40//如果考虑扩展,可以再以T_GamePlayerProxy来构造,形成有上限的多例模式(单例模式的扩展,因为实例都是已经构造好的,固定的) 41//没有提供new方法,外部不能想new几个就new几个,只能使用固定的那一个(或几个)实例(已经构造好的),因此是单例模式(或是其扩展)42const T_GamePlayer g_tGamePlayer;//私有变量放内部,单例模式4344#endif
1 /* **************************************************************************** 2 * Copyright (C) 2017-2018 Hanson Yu All rights reserved. 3 ------------------------------------------------------------------------------ 4 * File Module : GamePlayer.c 5 * Description : 代理模式 6 本文件是游戏角色 7 8 * Created : 2017.07.21. 9 * Author : Yu Weifeng 10 * Function List : 11 * Last Modified : 12 * History : 13 ***************************************************************************** */ 14 #include"stdio.h"15 #include"malloc.h"16 #include"stdlib.h"17 #include"string.h"18 #include"ProxyPattern.h"1920staticvoid SetGamePlayerName(char *i_strName); 21staticvoid GamePlayerLogin(char *i_strUserName,char *i_strPassword); 22staticvoid GamePlayerKillBoss(); 23staticvoid GamePlayerUpgrade(); 24staticchar *g_strGamePlayerName=NULL; 252627const T_GamePlayer g_tGamePlayer={ 28 .SetName =SetGamePlayerName, 29 .tIGamePlayer ={GamePlayerLogin,GamePlayerKillBoss,GamePlayerUpgrade}, 30}; 31/***************************************************************************** 32-Fuction : SetGamePlayerName 33-Description : 公有函数 34-Input : 35-Output : 36-Return : 37* Modify Date Version Author Modification 38* ----------------------------------------------- 39* 2017/07/21 V1.0.0 Yu Weifeng Created 40******************************************************************************/41staticvoid SetGamePlayerName(char *i_strName) 42{ 43 g_strGamePlayerName=i_strName; 44} 4546/***************************************************************************** 47-Fuction : GamePlayerLogin 48-Description : 公有函数 49-Input : 50-Output : 51-Return : 52* Modify Date Version Author Modification 53* ----------------------------------------------- 54* 2017/07/21 V1.0.0 Yu Weifeng Created 55******************************************************************************/56staticvoid GamePlayerLogin(char *i_strUserName,char *i_strPassword) 57{ 58 printf("登录名为%s的用户:%s,登录成功!\r\n",i_strUserName,g_strGamePlayerName); 59} 6061/***************************************************************************** 62-Fuction : GamePlayerKillBoss 63-Description : 公有函数 64-Input : 65-Output : 66-Return : 67* Modify Date Version Author Modification 68* ----------------------------------------------- 69* 2017/07/21 V1.0.0 Yu Weifeng Created 70******************************************************************************/71staticvoid GamePlayerKillBoss() 72{ 73 printf("%s 在打怪!\r\n",g_strGamePlayerName); 74} 7576/***************************************************************************** 77-Fuction : GamePlayerUpgrade 78-Description : 公有函数 79-Input : 80-Output : 81-Return : 82* Modify Date Version Author Modification 83* ----------------------------------------------- 84* 2017/07/21 V1.0.0 Yu Weifeng Created 85******************************************************************************/86staticvoid GamePlayerUpgrade() 87{ 88 printf("%s又升了一级!\r\n",g_strGamePlayerName); 89 }
3)执行结果:
book@book-desktop:/work/projects/test/DesignPatterns/ProxyPattern$ gcc -o ProxyPatternUsage
GamePlayer.c ProxyPattern.c ProxyPatternUsage.c
book@book-desktop:/work/projects/test/DesignPatterns/ProxyPattern$ ./ProxyPatternUsage
-----------------开始打游戏----------------
登录名为ZhangSan的用户:张三,登录成功!
张三 在打怪!
张三又升了一级!
4)详细代码:
https://github.com/fengweiyu/DesignThinking/tree/master/DesignPatterns/StructuralDesignPatterns/ProxyPattern
三、使用场景
1.不想参与中间过程的是是非非(具体由代理者处理),同时减轻负担
四、优点
1.职责清晰
真实的角色就是实现实际的业务逻辑,不用关心其他非本职责的事务,通过后期的代理完成一件事物,附带的结果就是编程简洁清晰。
2.高扩展性
具体主题角色是随时都会发生变化的,只要它实现了接口,甭管它如何变化,都是在接口之下,所以代理类完全就可以在不做任何修改的情况下使用
3.智能化
这在上诉的讲解中还没体现出来,主要在动态代理上得以体现
五、代理模式的扩展
1.普通代理和强制代理
1)普通代理就是我们要知道代理的存在,也就是类似的GamePlayerProxy这个类的存在,然后才能访问
即普通代理的要求就是客户端只能访问代理角色,而不能访问真实角色
普通代理的约束:真实的主题角色放在代理类内部创建对象,同时通过约定来静止new一个真实的角色,这样,调用这只知代理而不用知道真实的角色是谁,屏蔽了真实角色的变更对高层模块的影响,真实的主题角色想怎么修改就怎么修改,对高层模块没有任何影响,只要实现了接口所对应的方法。
2)强制代理则是调用者直接调用真实角色,而不用关心代理是否存在,其代理的产生是由真实角色决定的。
即必须通过真实角色查找到代理角色,也就是说真实角色管理代理角色(不允许直接访问真实角色),高层模块只要调用getProxy就可以访问真实角色的所有方法,它根本就不需要产生一个代理出来,代理的管理已经由真实角色自己完成。
注意:代理角色也可以再次被代理
2.代理是有个性的
代理类不仅仅可以实现主题接口,也可以实现其他接口完成不同的任务,而且代理的目的是在目标对象方法的基础上增强,这种增强的本质通常就是对目标对象的方法进行拦截和过滤。
3.虚拟代理
在需要的时候才初始化主题对象,可以避免被代理对象较多而引起的初始化缓慢的问题,其缺点是需要在每个方法中判断主题对象是否被创建,这就是虚拟代理。
4.动态代理
动态代理是在实现阶段不用关心代理谁,而在运行阶段才指定代理哪一个对象,相对来说,自己写代理类的方式就是静态代理。
动态代理事先(定义的时候)不知道代理谁,而C没有所有对象的父类都是object的概念以及反射的机制,所以很难实现。java的实现可参考其他书目
六、与其他模式的区别
1、代理模式与策略模式的区别:
差别就是策略模式的封装角色和被封装的策略类不用实现同一个接口,如果是同一个接口那就称为了代理模式。
2、代理模式与装饰模式
装饰模式就是代理模式的一个特殊应用,两者的共同点是都具有相同的接口,
不同点则是代理模式着重对代理过程的控制,它不对被代理类的功能做任何处理,保证原滋原味的调用。
而装饰模式则是对类的功能进行加强或减弱,它着重类的功能变化,它不做准入条件判断和准入参数过滤。
3、代理模式与其他包装模式的区别:
包装模式讲解完毕后说明
原文:http://www.cnblogs.com/yuweifeng/p/7230815.html
内容总结
以上是互联网集市为您收集整理的设计模式之代理模式20170724全部内容,希望文章能够帮你解决设计模式之代理模式20170724所遇到的程序开发问题。 如果觉得互联网集市技术教程内容还不错,欢迎将互联网集市网站推荐给程序员好友。
内容备注
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 gblab@vip.qq.com 举报,一经查实,本站将立刻删除。
内容手机端
扫描二维码推送至手机访问。