⑦ 设计模式的艺术-13.代理(Proxy)模式
为什么需要代理模式
- 中介隔离作用:在某些情况下,一个客户类不想或者不能直接引用一个委托对象,而代理类对象可以在客户类和委托对象之间起到中介的作用,其特征是代理类和委托类实现相同的接口。
- 开闭原则,增加功能:代理类除了是客户类和委托类的中介之外,我们还可以通过给代理类增加额外的功能来扩展委托类的功能,这样做我们只需要修改代理类而不需要再修改委托类,符合代码设计的开闭原则。代理类主要负责为委托类预处理消息、过滤消息、把消息转发给委托类,以及事后对返回结果的处理等。代理类本身并不真正实现服务,而是同过调用委托类的相关方法,来提供特定的服务。真正的业务功能还是由委托类来实现,但是可以在业务功能执行的前后加入一些公共的服务。例如我们想给项目加入缓存、日志这些功能,我们就可以使用代理类来完成,而没必要打开已经封装好的委托类。
核心作用:
• 通过代理,控制对对象的访问!
可以详细控制访问某个(某类)对象的方法,在调用这个方法前做前置处理,调用这个方法后
做后置处理。(即: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)模式的更多相关文章
- 设计模式C++描述----13.代理(Proxy)模式
一. 举例说明 我们有时打开一个网站时会发现有这样的现象,网站上的文字都显示出来了,但是上面的图片还没显示,要等一会才能显示. 这些未打开的图片的位置上,还是会有图片框和一些等待的信息的,这就是代理模 ...
- Head First 设计模式 —— 13. 代理 (Proxy) 模式
思考题 如何设计一个支持远程方法调用的系统?你要怎样才能让开发人员不用写太多代码?让远程调用看起来像本地调用一样,毫无瑕疵? P435 已经接触过 RPC 了,所以就很容易知道具体流程:客户端调用目标 ...
- 设计模式的征途—13.代理(Proxy)模式
所谓代购,简单说来就是找人帮忙购买所需要的商品.代购分为两种类型,一种是因为在当地买不到某件商品,又或者是因为当地这件商品的价格比其他地区的贵,因此托人在其他地区甚至国外购买该商品,然后通过快递发货或 ...
- 《图解设计模式》读书笔记9-2 Proxy模式
目录 Proxy模式 示例程序 程序描述 类图 程序 角色和类图 角色 模式类图 思路拓展 提升速度 代理与委托 Http代理 与其他模式的关联 Decorator模式 Proxy模式 Proxy是代 ...
- 代理(Proxy)模式简介
Proxy 模式简介 代理模式的两个应用: 打开文档时加载大图片 例如:如果有个对象是一张很大的图片,而这张图片需要花费很长时间才能显示出来,那么当这个图片包含在文档中的后面时,使用编辑器或浏览器打开 ...
- 设计模式之(三)Proxy模式
今天学习Proxy模式.代理模式是在对已有对象操作困难或者不太方便时,选择用代理的方式对对象进行访问.Proxy实现的方法必须和被代理对象一致. 举一个简单的例子, 有一个Math类实现了IMath接 ...
- 设计模式(二十一)Proxy模式
在面向对象编程中,“本人”和“代理人”都是对象.如果“本人”对象太忙了,有些工作无法自己亲自完成,就将其交给“代理人”对象负责. 示例程序的类图. 示例程序的时序图.从这个时序图可以看出,直到调用pr ...
- 设计模式--代理(Proxy)模式
在公司,经常性听到采购部的人说采购某样东材料,采购不了,需要通过代理商才可以.以前Insus.NET也做有一个练习<找人办事,代理设计模式(Proxy)>http://www.cnblog ...
- 十、设计模式之代理(Proxy)模式
什么是代理模式 代理模式是对象的结构模式,为其他对象提供一种对象以控制对这个对象的访问. 代理模式的结构图如下:(源自大话设计模式) Subject:定义了RealSubject和Proxy的公共 ...
随机推荐
- 常用的比较器:实现方式Compareable和Comparator
class Dog{ int size; int weight; public Dog(int s, int w){ size = s; weight = w; } } 目的:对于Dog对象作为元素所 ...
- 2nd 词频统计效能测试
词频统计效能测试 使用性能分析工具分析结果如下 :
- PAT 甲级 1008 Elevator
https://pintia.cn/problem-sets/994805342720868352/problems/994805511923286016 The highest building i ...
- 高性能的HTTP代理 LittleProxy
引用: https://github.com/adamfisk/LittleProxy 拦截和操纵HTTPS流量,LittleProxy使用中间人(MITM)管理器. LittleProxy的默认实现 ...
- (转)ActiveMQ的重连机制
花了一天的时间,终于搞明白了我的疑问. failover://(tcp://localhost:6168)?randomize=false&initialReconnectDelay=100& ...
- [二十]SpringBoot 之 (多)文件上传
(1)新建maven Java project 新建一个名称为spring-boot-fileuploadmaven java项目 (2)在pom.xml加入相应依赖: <project xml ...
- TCP的拥塞控制 (三)
1. Multiple Packet Losses Fast Retransmit/Fast Recovery机制可以很好地处理单个packet丢失的问题,但当大量packet同时丢包时(一个RT ...
- 【JQuery】数据
一.前言 接着前一章的内容,继续本章的学习 二.内容 queue 显示或操作在匹配元素上执行的函数队列 .queue(queueName) 操作在匹配元素上执行的函数队列 .queue( ...
- (转载)Cobalt Strike tutorial下针对CVE-2017-0199利用
CVE-2017-0199利用OLE对象嵌入Word / RTF文档的方式,使得可以在没有用户交互的情况下执行其内容.OLE由许多不同的程序支持,OLE通常用于使在另一个程序中可用的程序中创建的内容. ...
- Mac连接HDMI后没有声音
Mac连接HDMI后,会自动切换到HDMI设备进行发声,若HDMI设备没有声音,则不会发声.必须切换回内置扬声器才能有声音,或者拔出HDMI设备. 系统偏好设置 - 声音 - 输出 - 选择内置扬声 ...