代理模式(Proxy Pattern)是一个使用率非常高的模式,其定义如下:为其他对象提供一种代理以控制对这个对象的访问。

在某些情况下,一个客户不想或者不能直接引用另一个对象,而代理对象可以在客户端和目标对象之间起到中介的作用。

代理模式一般涉及到的角色有

1.抽象角色:声明真实对象和代理对象的共同接口

2.代理角色:代理对象角色内部含有对真实对象的引用,从而可以操作真实对象,同时代理对象提供与真实对象相同的接口以便在任何时刻都能代替真实对象。同时,代理对象可以在执行真实对象操作时,附加其他的操作,相当于对真实对象进行封装

3.真实角色:代理角色所代表的真实对象,是我们最终要引用的对象

代理模式的优点

1.职责清晰

真实的角色就是实现实际的业务逻辑,不用关心其他非本职责的事务,通过后期的代理完成一件事物,附带的结果就是编程简洁清晰。

2.高扩展性

具体主题角色是随时都会发生变化的,只要它实现了接口,甭管它如何变化,都逃不脱如来佛的手掌(接口),那我们的代理类完全就可以在不做任何修改的情况下使用。

3.智能化

通过动态代理,能够智能的代理委托角色。

代理模式分为静态代理和动态代理。

下面用个小例子说明一下静态代理,本例是个登录网络游戏,并打怪的例子。玩过网络游戏的都知道,打怪是很枯燥并且很累的过程,所以玩家就可以找代理(也就是游戏代练)来完成。

抽象主题角色,IGamePlayer

package com.zhouyu.proxy;

public interface IGamePlayer
{
//登录游戏
public void login(String user,String password); //打怪
public void killBoss(); //升级
public void upgrade();
}

具体主题角色,GamePlayer

package com.zhouyu.proxy;

public class GamePlayer implements IGamePlayer
{
private String name = ""; public GamePlayer(String name)
{
this.name = name;
} @Override
public void login(String user, String password)
{
System.out.println("登录名为:" + this.name + "登录成功");
} @Override
public void killBoss()
{
System.out.println(this.name + "在打怪");
} @Override
public void upgrade()
{
System.out.println(this.name + "又升了一级");
}
}

Proxy代理主题角色,GamePlayerProxy

package com.zhouyu.proxy;

public class GamePlayerProxy implements IGamePlayer
{
private IGamePlayer player; public GamePlayerProxy(IGamePlayer player)
{
this.player = player;
} @Override
public void login(String user, String password)
{
this.player.login(user,password);
} @Override
public void killBoss()
{
this.player.killBoss();
} @Override
public void upgrade()
{
this.player.upgrade();
}
}

客户端调用

package com.zhouyu.proxy;

import java.util.Date;

public class Client
{
public static void main(String[] args)
{
IGamePlayer player = new GamePlayer("张三");
IGamePlayer proxy = new GamePlayerProxy(player); System.out.println("开始游戏时间:" + new Date());
proxy.login("zhangsan","password");
proxy.killBoss();
proxy.upgrade();
System.out.println("结束游戏时间:" + new Date());
}
}

通过使用静态代理,那么真实角色必须是事先已经存在的,并将其作为代理对象的内部属性。但是实际使用时,一个真实角色必须对应一个代理角色,如果大量使用会导致类的急剧膨胀;此外,如果事先并不知道真实角色,该如何使用代理呢?这个问题可以通过Java的动态代理类来解决。

动态代理

Java动态代理类位于java.lang.reflect包下,一般主要涉及到以下两个类:

(1)Interface InvocationHandler:该接口中仅定义了一个方法

public object invoke(Object obj,Methodmethod, Object[] args)

在实际使用时,第一个参数obj一般是指代理类,method是被代理的方法,如上例中的request(),args为该方法的参数数组。这个抽象方法在代理类中动态实现。

(2)Proxy:该类即为动态代理类,其中主要包含以下内容

protected Proxy(InvocationHandler h):构造函数,用于给内部的h赋值。

static Class getProxyClass (ClassLoaderloader, Class[] interfaces):获得一个代理类,其中loader是类装载器,interfaces是真实类所拥有的全部接口的数组。

static Object newProxyInstance(ClassLoaderloader, Class[] interfaces, InvocationHandler h):返回代理类的一个实例,返回后的代理类可以当作被代理类使用(可使用被代理类的在Subject接口中声明过的方法)

所谓Dynamic Proxy是这样一种class:它是在运行时生成的class,在生成它时你必须提供一组interface给它,然后该class就宣称它实现了这些 interface。你当然可以把该class的实例当作这些interface中的任何一个来用。当然,这个Dynamic Proxy其实就是一个Proxy,它不会替你作实质性的工作,在生成它的实例时你必须提供一个handler,由它接管实际的工作

在使用动态代理类时,我们必须实现InvocationHandler接口

动态代理步骤

1.创建一个实现接口InvocationHandler的类,它必须实现invoke方法

2.创建被代理的类以及接口

3.通过Proxy的静态方法

newProxyInstance(ClassLoader loader,Class[] interfaces, InvocationHandler h) 创建一个代理

4.通过代理调用方法

下面用个例子来完成动态代理,跟静态代理的例子一样,同样是网络游戏的例子,抽象主题角色IGamePlayer和具体主题角色GamePlayer,Proxy代理主题角色采用动态的。

package com.zhouyu.dynamicProxy;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.util.Date; public class GamePlayerIH implements InvocationHandler
{
private Object object; public GamePlayerIH(Object object)
{
this.object = object;
} @Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable
{
System.out.println("开始游戏时间:" + new Date()); Object result = method.invoke(this.object,args);
if(method.getName().equals("login"))
{
System.out.println("有人登录我的帐号");
} System.out.println("结束游戏时间:" + new Date());
return result;
}
}

客户端调用

package com.zhouyu.dynamicProxy;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy; public class Client
{
public static void main(String[] args)
{
IGamePlayer player = new GamePlayer("张三");
InvocationHandler in = new GamePlayerIH(player); ClassLoader classLoader = player.getClass().getClassLoader();
IGamePlayer proxy = (IGamePlayer) Proxy.newProxyInstance(classLoader,
new Class[]{IGamePlayer.class},in);
proxy.login("zhangsan","password");
proxy.killBoss();
proxy.upgrade();
}
}

设计模式原来如此-代理模式(Proxy Pattern)的更多相关文章

  1. 乐在其中设计模式(C#) - 代理模式(Proxy Pattern)

    原文:乐在其中设计模式(C#) - 代理模式(Proxy Pattern) [索引页][源码下载] 乐在其中设计模式(C#) - 代理模式(Proxy Pattern) 作者:webabcd 介绍 为 ...

  2. 二十四种设计模式:代理模式(Proxy Pattern)

    代理模式(Proxy Pattern) 介绍为其他对象提供一个代理以控制对这个对象的访问. 示例有一个Message实体类,某对象对它的操作有Insert()和Get()方法,用一个代理来控制对这个对 ...

  3. c#设计模式之代理模式(Proxy Pattern)

    引言 代理这个词语,大家在现实世界已经频繁的接触过,例如火车站代理售票点,因为这些代理售票点的存在,我们不必要去火车站的售票处就可以查询或者取到火车票.代理点本身是没有能力生产车票的,我们在代理处享受 ...

  4. 乐在其中设计模式(C#) - 代理模式(Proxy Pattern)【转】

    介绍 为其他对象提供一个代理以控制对这个对象的访问. 示例 有一个Message实体类,某对象对它的操作有Insert()和Get()方法,用一个代理来控制对这个对象的访问. MessageModel ...

  5. 设计模式系列之代理模式(Proxy Pattern)——对象的间接访问

    说明:设计模式系列文章是读刘伟所著<设计模式的艺术之道(软件开发人员内功修炼之道)>一书的阅读笔记.个人感觉这本书讲的不错,有兴趣推荐读一读.详细内容也可以看看此书作者的博客https:/ ...

  6. 设计模式 - 代理模式(proxy pattern) 未使用代理模式 具体解释

    代理模式(proxy pattern) 未使用代理模式 详细解释 本文地址: http://blog.csdn.net/caroline_wendy 部分代码參考: http://blog.csdn. ...

  7. 代理模式(Proxy pattern)

    代理模式(proxy pattern):作用:为其他对象提供一种代理,以控制对这个对象的访问.代理对象在客户端对象和目标对象之间起中介的作用. 代理模式涉及到的角色: 抽象角色:声明真实对象和代理对象 ...

  8. 设计模式——代理模式(Proxy Pattern)

    代理模式(Proxy),为其他对象提供一种代理以控制对这个对象的访问. UML图: 模型设计: Subject类: package com.cnblog.clarck; /** * Subject 类 ...

  9. 13.代理模式(Proxy Pattern)

    using System; namespace Test { //抽象角色:声明真实对象和代理对象的共同接口. //代理角色:代理对象角色内部含有对真实对象的引用,从而可以操作真实对象, //同时代理 ...

  10. 大熊君说说JS与设计模式之------代理模式Proxy

    一,总体概要 1,笔者浅谈 当我们浏览网页时,网页中的图片有时不会立即展示出来,这就是通过虚拟代理来替代了真实的图片,而代理存储了真实图片的路径和尺寸,这就是代理方式的一种. 代理模式是比较有用途的一 ...

随机推荐

  1. ES5和ES6中对于继承的实现方法

    在ES5继承的实现非常有趣的,由于没有传统面向对象类的概念,Javascript利用原型链的特性来实现继承,这其中有很多的属性指向和需要注意的地方. 原型链的特点和实现已经在之前的一篇整理说过了,就是 ...

  2. Java开发和运行环境的搭建

    Java开发需要准备的东西? JDK+Eclipse 其中JDK的意思是Java开发工具包,Eclipse是进行用于做Java程序开发的工具(当然你也可以用记事本什么的去做). 其他开发工具:JCre ...

  3. java 13-1 数组高级二分查找

    查找: 1.基本查找:数组元素无序(从头找到尾) 2.二分查找(折半查找):数组元素有序 pS:数组的元素必须有顺序,从小到大或者从大到小.以下的分析是从小到大的数组 二分查找分析: A:先对数组进行 ...

  4. win10自动更新彻底关闭

    http://app.techweb.com.cn/wp/2016-10-24/2418646.shtml

  5. python案例-用户登录

    要求: •输入用户名密码 •认证成功后显示欢迎信息 •输错三次后锁定 1 #!/usr/bin/env python 2 # -*- coding:utf-8 -*- 3 4 "" ...

  6. 多线程BackgroundWorker

    链接:http://www.cnblogs.com/yiyisawa/archive/2008/11/24/1339826.html 周六闲来无事,学习了多线程BackgroundWorker,以此记 ...

  7. 取消StringGrid的自动滚动

    StringGrid的Options的goRowSelect为false时,在点击右侧未显示完全的Cell,StringGrid会自动向左滚动,怎样设定,取消StringGrid的自动滚动啊?Delp ...

  8. CAN开发中遇到的奇怪问题

    问题背景: 之前在做USBCAN2开发过程中,遇到一个奇葩问题,当我们加上其中某一句代码时,我们的程序会走不下去,得不到数据,而且在调试的过程中,你也不能暂停,不然,你也得不到数据.后来参考网上一篇帖 ...

  9. HTML基础 - <base>标签的使用

    标签对于不是很熟悉前端的人应该还算是个生面孔吧,粗略讲讲标签的用法. 将相对路径变成绝对路径 这个对于需要借(chao)鉴(xi)别人网页的时候特别有用~ 批量设置target=_blank 当需要对 ...

  10. WPS2013三合一全套精品视频教程-【word,excel,powerpoint】

    WPS2013三合一全套精品视频教程-[word,excel,powerpoint]教程目录: 下载地址:http://www.fu83.cn/thread-184-1-1.html