代理(Proxy)模式一
来源:互联网 发布:erp软件系统 报表 编辑:程序博客网 时间:2024/05/21 19:23
1.类图和角色
定义:Provide a surrogate or placeholder for another object to control access to it.(为其他对象提供一种代理以控制对这个对象的访问)。
代理模式涉及的角色有:
- 抽象主题角色:声明了真实主题和代理主题的共同接口,以便在任何可以使用真实主题的地方都可以使用代理角色。
- 代理主题(Proxy)角色:代理主题角色内部含有对真实主题的引用,从而可以在任何时候操作真实主题对象;与真实对象有共同的接口,以便可以在任何时候都可以代替真实对象;控制对真实对象的引用,负责在需要的时候操作真实的主题对象;通常,代理将调用传递给真实对象之前或之后,都要执行某些操作,而不是单纯的传递。
- 真实主题(RealSubject)角色:定义了代理所代表的真实对象。
2.示例代码
抽象主题的代码:
public abstract class Subject { public abstract void request();}
真实主题的代码:
public class RealSubject extends Subject { public RealSubject() {} public void request() { System.out.println("Real subject"); }}
代理主题角色的代码:可以看出,代理主题处理将所有的请求委派给真实主题角色之外,还在委派之前和之后分别执行了一个preRequest()和postRequest()。
public class ProxySubject extends Subject { private RealSubject realSubject; public ProxySubject() {} public void request() { preRequest(); if (realSubject == null) { realSubject = new RealSubject(); } //调用真实对象的业务方法 realSubject.request(); postRequest(); } private void preRequest() { //在执行request()之前,要执行的代码 } private void postRequest() { //在执行request()之后,要执行的代码 }}
在使用代理主题的时候,要将变量声明类型声明为抽象主题的类型,而将真实的类型设为代理主题类型,代码如下:
Subject subject = new ProxySubject(); subject.request();
从以上的代码可以看出代理是怎样工作的,首先,代理主题不改变主题接口;其次,地理主题起到的是一个传递请求的作用;最后代理主题在传递请求之前和之后可以执行特定的操作,而不是单纯的传递请求。
3.代理模式的应用
代理模式在现实中的使用非常多,非常典型的应用就是Spring AOP。还有就是java web应用中的Filter,它也是非常典型的代理的应用。
4.代理模式的扩展
4.1普通代理
普通代理的要求就是客户端只能访问代理角色,而不能访问真实角色。我们以游戏代练的场景为例,游戏代练者与实际的玩家有共同的接口,游戏代练者使用玩家的账号登录游戏,升级打怪,真实玩家支付一定的费用给游戏代练者。类图如下:
玩家接口代码如下:
public interface IGamePlayer { public void login(String user, String password); public void killBoss(); public void upgrade();}
玩家代码:
public class GamePlayer implements IGamePlayer { private String name = ""; public GamePlayer(IGamePlayer gamePlayer, String name) { if (gamePlayer == null) { throw new RuntimeException("不能创建真实角色"); } else { this.name = name; } } @Override public void killBoss() { //打怪 } @Override public void login(String user, String password) { //登录 } @Override public void upgrade() { //升级 }}
游戏代练者的代码:
public class GamePlayerProxy implements IGamePlayer { private IGamePlayer gamePlayer = null; public GamePlayerProxy(String name) { gamePlayer = new GamePlayer(this, name); } @Override public void killBoss() { this.gamePlayer.killBoss(); } @Override public void login(String user, String password) { this.gamePlayer.login(user, password); } @Override public void upgrade() { this.gamePlayer.upgrade(); }}
调用者代码:
IGamePlayer proxy = new GamePlayerProxy("李四"); proxy.login("zhansan", "123"); proxy.killBoss(); proxy.upgrade();
调用者只知道代理而不用知道真实的角色是谁,屏蔽了真实角色的变更对高层模块的影响,真实角色想怎么改就怎么改,对高层没有任何的影响。在实际的项目中,一般都是通过约定来禁止new一个真实的角色。
4.2强制代理
强制代理是要强制必须通过真实角色查找到代理角色,否则不能访问。无论是通过代理类还是通过new生成一个真实角色,都不能访问,只能通过真实角色指定的代理类才可以访问。也就是说,客户端new一个真实角色对象,返回的却是代理角色。类图如下:
强制代理的接口代码
public interface IGamePlayer { public void login(String name, String password); public void killBoss(); public void upgrade(); public IGamePlayer2 getProxy();}
强制代理的真实角色代码:
public class GamePlayer implements IGamePlayer { private String name = ""; private IGamePlayer proxy = null; public GamePlayer(String name_) { this.name = name_; } @Override public void login(String name, String password) { if (isProxy()) { System.out.println(this.name + "登录了!"); } else { System.out.println("请使用代理访问"); } } @Override public void killBoss() { if (isProxy()) { System.out.println(this.name + "打怪!"); } else { System.out.println("请使用代理访问"); } } @Override public void upgrade() { if (isProxy()) { System.out.println(this.name + "升级了!"); } else { System.out.println("请使用代理访问"); } } @Override public IGamePlayer getProxy() { this.proxy = new GamePlayerProxy2(this); return this.proxy; } private boolean isProxy() { return (this.proxy == null ? false : true); }}
增加了一个私有方法,用了检查是否是自己指定的代理对象。再来看看代理角色的代码:
public class GamePlayerProxy implements IGamePlayer { private IGamePlayer gamePlayer = null; public GamePlayerProxy(IGamePlayer gamePlayer) { this.gamePlayer = gamePlayer; } @Override public void login(String name, String password) { this.gamePlayer.login(name, password); } @Override public void killBoss() { this.gamePlayer.killBoss(); } @Override public void upgrade() { this.gamePlayer.upgrade(); } @Override public IGamePlayer2 getProxy() { return this; }}
客户端调用代码:
//通过真实主题角色获取代理,再访问方法 IGamePlayer2 gamePlayer = new GamePlayer2("张三"); IGamePlayer2 proxy = gamePlayer.getProxy(); proxy.login("zhansan", "123"); proxy.upgrade(); proxy.killBoss(); //真实对象直接访问 IGamePlayer2 gamePlayer2 = new GamePlayer2("张三"); gamePlayer2.killBoss(); gamePlayer2.login("lili", "123");
运行代码可见,通过真实对象是不能直接访问方法的。由代码可以看出,强制代理的概念就是要从真实角色查找到代理角色,不允许直接访问真实角色。
- 一、 代理(Proxy)模式
- 代理(Proxy)模式一
- 代理模式(Proxy)一 静态代理
- 代理(Proxy)模式
- 代理(Proxy)模式
- 代理(Proxy)模式
- proxy(代理)模式
- 代理模式(Proxy)
- 代理模式(Proxy)
- 代理模式(Proxy)
- Proxy(代理模式)
- 代理(proxy)模式
- 代理模式(Proxy)
- Proxy(代理)模式
- 代理模式(PROXY)
- 代理模式(Proxy)
- 代理(proxy)模式
- 代理模式(Proxy)
- 整理:深度学习 vs 机器学习 vs 模式识别
- 栈和堆的区别是什么? 为什么说栈的速度快,堆的速度慢?
- Java 泛型
- 微信服务器在填写服务器的配置返回token验证失败
- js数组引用传值问题
- 代理(Proxy)模式一
- Android 百分比布局库(percent-support-lib) 解析与扩展
- php开发环境搭建
- 工作五年以上的程序员,应该干些什么
- 面向对象
- session
- git命令大全
- jstl 使用mgt标签将数字转换时间
- 静态全局变量