为什么需要代理模式

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

    题目: E. Arthur and Brackets time limit per test 2 seconds memory limit per test 128 megabytes input s ...

  2. javascript之彻底理解valueOf, toString

    参与运算的都是简单类型(一般就字符串和数字), 复杂类型是不参与运算的. ***当对象(非简单类型)用作键时,会先调用toString()方法把对象转化成字符串 var a = {},     b = ...

  3. json 和 pickle

    用于序列化的两个模块 json:用于字符串和python数据类型间进行转换 pickle:用于python特有的类型和python的数据类型间进行转换 json模块提供了四个功能:dumps dump ...

  4. MySQL专题3 SQL 优化

    这两天去京东面试,面试官问了我一个问题,如何优化SQL 我上网查了一下资料,找到了不少方法,做一下记录 (一). 首先使用慢查询分析  通过Mysql 的Slow Query log 可以找到哪些SQ ...

  5. Beats Solo3 Wireless 无法链接 MacBook pro

    Beats Solo3 Wireless 无法链接 MacBook pro 问题解决了,原来只要长按耳机的开关按钮就能被识别到了,貌似需要5秒钟不松手. https://bbs.feng.com/re ...

  6. IIS部署时failed to execute url 解决方法

    web.config中增加如下节点: <system.webServer>  <validation validateIntegratedModeConfiguration=&quo ...

  7. HDU 4758——Walk Through Squares——2013 ACM/ICPC Asia Regional Nanjing Online

    与其说这是一次重温AC自动机+dp,倒不如说这是个坑,而且把队友给深坑了. 这个题目都没A得出来,我只觉得我以前的AC自动机的题目都白刷了——深坑啊. 题目的意思是给你两个串,每个串只含有R或者D,要 ...

  8. BZOJ 2957 楼房重建(线段树区间合并)

    一个显而易见的结论是,这种数字的值是单调递增的.我们修改一个数只会对这个数后面的数造成影响.考虑线段树划分出来的若干线段. 这里有两种情况: 1.某个线段中的最大值小于等于修改的数,那么这个线段的贡献 ...

  9. p12转pem公钥私钥

    cer格式证书生成p12文件,前面写了有一篇了. 这里是从p12文件导出公钥和私钥 //1.生成1.key文件 openssl pkcs12 -in apple_payment.p12 -nocert ...

  10. Day21-自定义simple_tag/filter

    一. 在模板里面对用户发过来的数据进行二次加工.想办法把Python的函数放到模板语言里面使用. 有2种方法:filter与simple_tag 二. 实例 {{name|lower}} trunca ...