、引子
我们去科技市场为自己
机器添加点奢侈
配件
很多DIYer都喜欢去找代理商
在代理商那里拿到
东西不仅质量有保证
而且价格和售后服务上都会好很多
客户通过代理商得到了自己想要
东西
而且还享受到了代理商额外
服务;而生产厂商通过代理商将自己
产品推广出去
而且可以将
些销售服务
任务交给代理商来完成(当然代理商要和厂商来共同分担风险
分配利润)
这样自己就可以花更多
心思在产品
设计和生产上了
在美国
任何企业
产品要想拿到市场上去卖就必须经过代理商这
个环节
否则就是非法
看来代理商在商业运作中起着很关键
作用
不小心把话题扯远了
回过头来
那么在我们
面向对象
设计中
会不会有代理商这样
角色呢?来看这篇文章
人肯定不会说:没有!
那么就跟着这篇文章来看看代理模式
奇妙吧
2、定义和分类
代理模式在设计模式中
定义就是:为其他对象提供
种代理以控制对这个对象
访问
说白了就是
在
些情况下客户不想或者不能直接引用
个对象
而代理对象可以在客户和目标对象的间起到中介作用
去掉客户不能看到
内容和服务或者增添客户需要
额外服务
那么什么时候要使用代理模式呢?在对已有
思路方法进行使用
时候出现需要对原有思路方法进行改进或者修改
这时候有两种改进选择:修改原有思路方法来适应现在
使用方式
或者使用
个“第 3者”思路方法来
原有
思路方法并且对思路方法产生
结果进行
定
控制
第
种思路方法是明显违背了“对扩展开放、对修改关闭”(开闭原则)
而且在原来思路方法中作修改可能使得原来类
功能变得模糊和多元化(就像现在企业多元化
样)
而使用第 2种方式可以将功能划分
更加清晰
有助于后面
维护
所以在
定程度上第 2种方式是
个比较好
选择!
当然
话又说回来了
如果是
个很小
系统
功能也不是很繁杂
那么使用代理模式可能就显得臃肿
不如第
种方式来
快捷
这就像
个 3口的家
家务活全由家庭主妇或者
个保姆来完成是比较合理
根本不需要雇上好几个保姆层层代理:)
根据
Java和模式
书中对代理模式
分类
代理模式分为8种
这里将几种常见
、重要
列举如下:
1. 远程(Remote)代理:为
个位于区别
地址空间
对象提供
个局域代表对象
比如:你可以将
个在世界某个角落
台机器通过代理假象成你局域网中
部分
2. 虚拟(Virtual)代理:根据需要将
个资源消耗很大或者比较复杂
对象延迟
真正需要时才创建
比如:如果
个很大
图片
需要花费很长时间才能显示出来
那么当这个图片包含在文档中时
使用编辑器或浏览器打开这个文档
这个大图片可能就影响了文档
阅读
这时需要做个图片Proxy来代替真正
图片
3. 保护(Protect or Access)代理:控制对
个对象
访问权限
比如:在论坛中
区别
身份登陆
拥有
权限是区别
使用代理模式可以控制权限(当然
使用别
方式也可以实现)
4. 智能引用(Smart Reference)代理:提供比对目标对象额外
服务
比如:纪录访问
流量(这是个再简单不过
例子)
提供
些友情提示等等
代理模式是
种比较有用
模式
从几个类
“小结构”到庞大系统
“大结构”都可以看到它
影子
3、结构
代理模式中
“代理商”要想实现代理任务
就必须和被代理
“厂商”使用共同
接口(你可以想象为产品)
所以自然而然你会想到在java中使用
个抽象类或者接口(推荐)来实现这个共同
接口
于是代理模式就有 3个角色组成了:
1.抽象主题角色:声明了真实主题和代理主题
共同接口
2.代理主题角色:内部包含对真实主题
引用
并且提供和真实主题角色相同
接口
3.真实主题角色:定义真实
对象
使用类图来表示下 3者间
关系如下:
当然
图上所示
是代理模式中
个具体情况
而代理模式可以非常灵活
使用其他方式来实现
这样就和图上所示有很大
区别
也许
现在你已经对代理模式已经有了
个宏观
认识了
下面我们来看看如何实际
使用代理模式
4、举例
以论坛中已注册用户和游客
权限区别来作为第
个例子:已注册
用户拥有发帖
修改自己
注册信息
修改自己
帖子等功能;而游客只能看到别人发
帖子
没有其他权限
为了简化代码
更好
显示出代理模式
骨架
我们这里只实现发帖权限
控制
首先我们先实现
个抽象主题角色MyForum
里面定义了真实主题和代理主题
共同接口——发帖功能
代码如下:
public
erface MyForum
{
public void AddFile
;
}
这样
真实主题角色和代理主题角色都要实现这个接口
其中真实
主题角色基本就是将这个接口
思路方法内容填充进来
所以在这里就不再赘述它
实现
我们把主要
精力放到关键
代理主题角色上
代理主题角色代码大体如下:
public
MyForumProxy implements MyForum
{
private RealMyForum forum ;
private
permission ; //权限值
public MyForumProxy(
permission)
{
forum =
RealMyForum
this.permission = permission ;
}
//实现
接口
public void AddFile
{
//满足权限设置
时候才能够执行操作
//Constants是
个常量类
(Constants.ASSOCIATOR
permission)
{
forum.AddFile
;
}
.out.pr
ln("You are not a associator of MyForum ,please registe!");
}
}
这样就实现了代理模式
功能
当然你也可以在这个代理类上添加自己
思路方法来实现额外
服务
比如统计帖子
浏览次数
记录用户
登录情况等等
还有
个很常见
代理模式
使用例子就是对大幅图片浏览
控制
在我们常见
网站WebSite上面浏览图文
信息时
不知道你有没有注意到
图片位置放置
是经过缩小
当有人要仔细
查看这个图片时
可以通过点击图片来激活
个链接
在
个新
网页打开要看
图片
这样对于提高浏览速度是很有好处
不是每个人都要去看仔细图上
信息
这种情况就可以使用代理模式来全面实现
这里我将思路表述出来
至于实现由于工作原因
就不表述了
至于这种方式在B/S模式下
真实可行性
我没有确认过
只是凭空
想象
如果不是可行
方式
那这个例子可以放到
个C/S下来实现
这个是绝对没有问题
而且在很多介绍设计模式
书和文章中使用
两种方式
实现有兴趣
可以来尝试
下
我们在浏览器中访问网页时是
不是真实
装载图片
思路方法
而是在代理对象中
思路方法
在这个对象中
先使用
个线程向浏览器装载了
个缩小版
图片
而在后台使用另
个线程来
真实
装载大图片
思路方法将图片加载到本地
当你要浏览这个图片
时候
将其在新
网页中显示出来
当然如果在你想浏览
时候图片尚未加载成功
可以再启动
个线程来显示提示信息
直到加载成功
这样代理模式
功能就在上面体现
淋漓尽致——通过代理来将真实图片
加载放到后台来操作
使其不影响前台
浏览
5、整理总结
代理模式能够协调
者和被
者
能够在
定程度上降低系统
耦合度
不过
定要记住前面讲
使用代理模式
条件
不然
话使用了代理模式不但不会有好
效果
说不定还会出问题
延伸阅读
最新评论