为什么需要代理模式

  • 中介隔离作用:在某些情况下,一个客户类不想或者不能直接引用一个委托对象,而代理类对象可以在客户类和委托对象之间起到中介的作用,其特征是代理类和委托类实现相同的接口。
  • 开闭原则,增加功能:代理类除了是客户类和委托类的中介之外,我们还可以通过给代理类增加额外的功能来扩展委托类的功能,这样做我们只需要修改代理类而不需要再修改委托类,符合代码设计的开闭原则。代理类主要负责为委托类预处理消息、过滤消息、把消息转发给委托类,以及事后对返回结果的处理等。代理类本身并不真正实现服务,而是同过调用委托类的相关方法,来提供特定的服务。真正的业务功能还是由委托类来实现,但是可以在业务功能执行的前后加入一些公共的服务。例如我们想给项目加入缓存、日志这些功能,我们就可以使用代理类来完成,而没必要打开已经封装好的委托类。
  • 核心作用:
    • 通过代理,控制对对象的访问!
    可以详细控制访问某个(某类)对象的方法,在调用这个方法前做前置处理,调用这个方法后
    做后置处理。(即:AOP的微观实现!)
    – AOP(Aspect Oriented Programming面向切面编程)的核心实现机制!

什么是代理模式?

       代理模式的定义:代理模式给某一个对象提供一个代理对象,并由代理对象控制对原对象的引用。通俗的来讲代理模式就是我们生活中常见的中介。

有哪几种代理模式?

  我们有多种不同的方式来实现代理。如果按照代理创建的时期来进行分类的话, 可以分为两种:静态代理、动态代理

  静态代理是由程序员创建或特定工具自动生成源代码,在对其编译。在程序员运行之前,代理类.class文件就已经被创建了。

  动态代理是在程序运行时通过反射机制动态创建的。

  代理模式 为真实对象提供一个代理, 从而控制对真实对象的访问 。

静态代理

代理模式包含如下角色:

Subject:抽象主题角色。可以是接口,也可以是抽象类。

RealSubject:真实主题角色。业务逻辑的具体执行者。

ProxySubject:代理主题角色。内部含有RealSubject的引用,负责对真实角色的调用,并在真实主题角色处理前后做预处理和善后工作。

代理模式优点:

职责清晰 真实角色只需关注业务逻辑的实现,非业务逻辑部分,后期通过代理类完成即可。

高扩展性 不管真实角色如何变化,由于接口是固定的,代理类无需做任何改动。

代码示例

•抽象角色

  定义代理角色和真实角色的公共对外方法

•真实角色

  实现抽象角色,定义真实角色所要实现的业务逻辑,供代理角色调用。

  关注真正的业务逻辑!

•代理角色

  实现抽象角色,是真实角色的代理,通过真实角色的业务逻辑方法来实现抽象方法,并可以附加自己的操作。

  将统一的流程控制放到代理角色中处理!

Star

package com.cnki.proxy.dynamicProxy;

public interface Star {
/**
* 面谈--代理人去做
*/
void confer();
/**
* 签合同--代理人去做
*/
void signContract();
/**
* 订票--代理人去做
*/
void bookTicket();
/**
* 唱歌--本人去做
*/
void sing();
/**
* 收钱--代理人去做
*/
void collectMoney();
}

RealStar

package com.cnki.proxy.dynamicProxy;

public class RealStar implements Star {

    @Override
public void bookTicket() {
System.out.println("RealStar.bookTicket()");
} @Override
public void collectMoney() {
System.out.println("RealStar.collectMoney()");
} @Override
public void confer() {
System.out.println("RealStar.confer()");
} @Override
public void signContract() {
System.out.println("RealStar.signContract()");
} @Override
public void sing() {
System.out.println("RealStar(周杰伦本人).sing()");
} }

ProxyStar

package com.cnki.proxy.dynamicProxy;

public class ProxyStar implements Star {

    private Star star;

    public ProxyStar(Star star) {
super();
this.star = star;
} @Override
public void bookTicket() {
System.out.println("ProxyStar.bookTicket()");
} @Override
public void collectMoney() {
System.out.println("ProxyStar.collectMoney()");
} @Override
public void confer() {
System.out.println("ProxyStar.confer()");
} @Override
public void signContract() {
System.out.println("ProxyStar.signContract()");
} @Override
public void sing() {
star.sing();
} }

测试

package com.cnki.proxy.dynamicProxy;

public class Client {
public static void main(String[] args) {
Star real = new RealStar();
Star proxy = new ProxyStar(real); proxy.confer();
proxy.signContract();
proxy.bookTicket();
proxy.sing(); proxy.collectMoney(); }
}

应用场景

– 安全代理:屏蔽对真实角色的直接访问。

– 远程代理:通过代理类处理远程方法调用(RMI)

– 延迟加载:先加载轻量级的代理对象,真正需要再加载真实对象。

• 比如你要开发一个大文档查看软件,大文档中有大的图片,有可能一个图片有100MB,在打开文件时不可能将所有的图片都显示出来,这样就可以使用代理模式,当需要查看图片时,用proxy来进行大图片的打开。

动态代理

  动态代理相比于静态代理的优点:抽象角色中(接口)声明的所以方法都被转移到调用处理器一个集中的方法中处理,这样,我们可以更加灵活和统一的处理众多的方法。

  JDK自带的动态代理

  java.lang.reflect.Proxy

  作用:动态生成代理类和对象

  java.lang.reflect.InvocationHandler(处理器接口)

  可以通过invoke方法实现对真实角色的代理访问

  每次通过Proxy生成代理类对象对象时都要指定对应的处理器对象

Star

package com.cnki.proxy.dynamicProxy;

public interface Star {
/**
* 面谈
*/
void confer();
/**
* 签合同
*/
void signContract();
/**
* 订票
*/
void bookTicket();
/**
* 唱歌
*/
void sing();
/**
* 收钱
*/
void collectMoney();
}

RealStar

package com.cnki.proxy.dynamicProxy;

public class RealStar implements Star {

    @Override
public void bookTicket() {
System.out.println("RealStar.bookTicket()");
} @Override
public void collectMoney() {
System.out.println("RealStar.collectMoney()");
} @Override
public void confer() {
System.out.println("RealStar.confer()");
} @Override
public void signContract() {
System.out.println("RealStar.signContract()");
} @Override
public void sing() {
System.out.println("RealStar(周杰伦本人).sing()");
} }

StarHandler

package com.cnki.proxy.dynamicProxy;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method; public class StarHandler implements InvocationHandler { Star realStar; public StarHandler(Star realStar) {
super();
this.realStar = realStar;
} @Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object object = null; System.out.println("真正的方法执行前!");
System.out.println("面谈,签合同,预付款,订机票"); if(method.getName().equals("sing")){
object = method.invoke(realStar, args);
} System.out.println("真正的方法执行后!");
System.out.println("收尾款");
return object;
} }

测试

package com.cnki.proxy.dynamicProxy;

import java.lang.reflect.Proxy;

public class Client {
public static void main(String[] args) { Star realStar = new RealStar();
StarHandler handler = new StarHandler(realStar); Star proxy = (Star) Proxy.newProxyInstance(ClassLoader.getSystemClassLoader(), new Class[]{Star.class}, handler); proxy.sing(); } }

开发框架中应用场景

  struts2中拦截器的实现

  数据库连接池关闭处理

  Hibernate中延时加载的实现

  mybatis中实现拦截器插件

  AspectJ的实现

  spring中AOP的实现

  日志拦截

   声明式事务处理

  web service

  RMI远程方法调用

⑦ 设计模式的艺术-13.代理(Proxy)模式的更多相关文章

  1. 设计模式C++描述----13.代理(Proxy)模式

    一. 举例说明 我们有时打开一个网站时会发现有这样的现象,网站上的文字都显示出来了,但是上面的图片还没显示,要等一会才能显示. 这些未打开的图片的位置上,还是会有图片框和一些等待的信息的,这就是代理模 ...

  2. Head First 设计模式 —— 13. 代理 (Proxy) 模式

    思考题 如何设计一个支持远程方法调用的系统?你要怎样才能让开发人员不用写太多代码?让远程调用看起来像本地调用一样,毫无瑕疵? P435 已经接触过 RPC 了,所以就很容易知道具体流程:客户端调用目标 ...

  3. 设计模式的征途—13.代理(Proxy)模式

    所谓代购,简单说来就是找人帮忙购买所需要的商品.代购分为两种类型,一种是因为在当地买不到某件商品,又或者是因为当地这件商品的价格比其他地区的贵,因此托人在其他地区甚至国外购买该商品,然后通过快递发货或 ...

  4. 《图解设计模式》读书笔记9-2 Proxy模式

    目录 Proxy模式 示例程序 程序描述 类图 程序 角色和类图 角色 模式类图 思路拓展 提升速度 代理与委托 Http代理 与其他模式的关联 Decorator模式 Proxy模式 Proxy是代 ...

  5. 代理(Proxy)模式简介

    Proxy 模式简介 代理模式的两个应用: 打开文档时加载大图片 例如:如果有个对象是一张很大的图片,而这张图片需要花费很长时间才能显示出来,那么当这个图片包含在文档中的后面时,使用编辑器或浏览器打开 ...

  6. 设计模式之(三)Proxy模式

    今天学习Proxy模式.代理模式是在对已有对象操作困难或者不太方便时,选择用代理的方式对对象进行访问.Proxy实现的方法必须和被代理对象一致. 举一个简单的例子, 有一个Math类实现了IMath接 ...

  7. 设计模式(二十一)Proxy模式

    在面向对象编程中,“本人”和“代理人”都是对象.如果“本人”对象太忙了,有些工作无法自己亲自完成,就将其交给“代理人”对象负责. 示例程序的类图. 示例程序的时序图.从这个时序图可以看出,直到调用pr ...

  8. 设计模式--代理(Proxy)模式

    在公司,经常性听到采购部的人说采购某样东材料,采购不了,需要通过代理商才可以.以前Insus.NET也做有一个练习<找人办事,代理设计模式(Proxy)>http://www.cnblog ...

  9. 十、设计模式之代理(Proxy)模式

    什么是代理模式 代理模式是对象的结构模式,为其他对象提供一种对象以控制对这个对象的访问. 代理模式的结构图如下:(源自大话设计模式)   Subject:定义了RealSubject和Proxy的公共 ...

随机推荐

  1. struts2 action json(还有servlet的)

    http://yshjava.iteye.com/blog/1333104 留着 版权声明:本文为博主原创文章,未经博主允许不得转载.

  2. HDU 5228 ZCC loves straight flush 暴力

    题目链接: hdu:http://acm.hdu.edu.cn/showproblem.php?pid=5228 bc(中文):http://bestcoder.hdu.edu.cn/contests ...

  3. 团队作业4——第一次项目冲刺(Alpha版本)第一次

    一.会议内容 制定任务内容 制作leangoo表格 初步工作 二.各人工作 成员 计划任务 遇见难题 贡献比 塗家瑜(组长) 后端与数据库通讯 无 1 张新磊 表设计 无 1 姚燕彬 测试计划编写 无 ...

  4. 4th 课堂SCRM会议旁观记录

    项目名称:基于C#的连连看设计 小组名称:待定 小组成员:张政.张金生.武志远.李权 Master:张政 项目已完成部分: 现阶段已经实现了一定的功能,可以运行使用,进行第一关的游戏. 今天计划要完成 ...

  5. 【week11】psp

    本周psp 项目 内容 开始时间 结束时间 被打断 净时间 11.26(星期六)  看论文 psiBlast  9:00 12:00  5  175    11.28(星期一)  做作业 设计模式作业 ...

  6. python3.6 SSL module is not available

    pip is configured with locations that require TLS/SSL, however the ssl module in Python is not avail ...

  7. BZOJ 2462 矩阵模板(二维hash)

    题意:给出一个n*m的01矩阵,以及k个a*b的01矩阵,问每个是否能匹配原来的01矩阵. 由于k个矩阵的长和宽都是一样的,所以把原矩阵的所有a*b的子矩阵给hash出来.然后依次查找是否存在即可. ...

  8. bzoj2699 更新

    题意 对于一个数列A[1..N],一种寻找最大值的方法是:依次枚举A[2]到A[N],如果A[i]比当前的A[1]值要大,那么就令A[1]=A[i],最后A[1]为所求最大值.假设所有数都在范围[1, ...

  9. 【bzoj2402】陶陶的难题II 分数规划+树链剖分+线段树+STL-vector+凸包+二分

    题目描述 输入 第一行包含一个正整数N,表示树中结点的个数.第二行包含N个正实数,第i个数表示xi (1<=xi<=10^5).第三行包含N个正实数,第i个数表示yi (1<=yi& ...

  10. VSS2005清除管理员密码

    1.下载工具ultraedit 2.登录到服务器,找到VSS库文件夹,data\um.dat 3.复制到自己桌面,用ultraedit打开,进入 引用内容 00000080h: 55 55 03 29 ...