Java设计模式之代理模式

简介:
代理模式,定义为,为另一对象提供一个占位符或者替身以控制对这个对象的访问。故代理模式核心思想就是控制对象访问。
使用代理模式创建代理,可以让代表对象控制某一个对象的访问,该被代表对象可以是远程对象,创建开销大的对象或者需要安全控制的对象。
几种常见的代理控制访问方式:
1)远程代理控制访问远程对象
2)虚拟代理控制访问创建开销大的资源
3)保护代理基于权限控制对资源的访问
代理模式的基本类图
152945602.jpg
Proxy和RealSubject都实现了共同的接口,这允许任何客户都可以像处理RealSubject一样处理Proxy
RealSubject通常是真正做事的对象,proxy会控制对RealSubject的访问。
Proxy持有Subject引用,它可以创建RealSubject对象,来将请求转发给Subject
远程代理
远程代理其实就是远程对象在本地代表,或者说是另一个jvm堆上的对象在本jvm堆中的代表。本地代表,指的就是一种可以由本地方法调用的对象,其行为会转发到远程对象中。
在利用远程代理中,客户对象操作的就是远程对象在本地的代理,客户对象所做的就像是在做远程方法调用,但其实只是调用本地堆中的“代理”对象的方法,再由该代理对象处理所有网络通信的底层细节。
为了实现远程代理,调用远程方法,一般我们就利用RMI(Remote Method Invocation),RMI可以让我们找到远程JVM内的对象,并且允许我们调用它们的方法。关于如何实现RMI的,请参见另一个博客介绍,《Java远程方法调用RMI的实现》
虚拟代理
虚拟代理主要是作为创建开销大的对象的代表,虚拟代理经常直到我们真正需要一个对象的时候才创建它,当对象在创建前和创建中的时候,由虚拟代理来扮演对象的替身。对象创建完后,代理就会将请求直接委托给对象。
保护代理
保护代理,就是根据访问权限决定客户是否可以访问对象的代理。
一般保护代理就是通过动态代理来实现的,现在就主要讨论一下动态代理如何实现及流程。
动态代理
Java.lang.reflect包有对于代理的支持,可以在运行的时候动态创建一个代理类,实现一个或者多个接口,并将方法的调用转发到你所指定的类。在java中创建动态代理,必须要为你要创建的类先定义一个接口。
动态代理类图如下:
184032264.jpg
动态代理过程中,是由java内置的创建一个proxy类,该类同样是实现了Subject接口,由于该代理类是由java动态创建的,不能将逻辑代码放置到Proxy类里面,则就放置到InvocationHandler中,它主要是相应代理的任何调用信息,当代理收到方法调用的时候,都是委托给 InvocationHandler做的。
Proxy 的静态方法
该方法用于获取指定代理对象所关联的调用处理器 
static InvocationHandler getInvocationHandler(Object proxy) 
该方法用于获取关联于指定类装载器和一组接口的动态代理类的类对象 
static Class getProxyClass(ClassLoader loader, Class[] interfaces) 
该方法用于判断指定类对象是否是一个动态代理类 
static boolean isProxyClass(Class cl) 
该方法用于为指定类装载器、一组接口及调用处理器生成动态代理类实例 
static Object newProxyInstance(ClassLoader loader, Class[] interfaces, InvocationHandler h)
InvocationHandler 的核心方法
第一个参数是代理类实例,第二个参数是被调用的方法对象,第三个方法是调用参数
调用处理器根据这三个参数进行预处理或分派到委托类实例上发射执行 
Object invoke(Object proxy, Method method, Object[] args)
使用 Java 动态代理的具体步骤:
1. 通过实现 InvocationHandler 接口创建自己的调用处理器,并且提供一个方法设置代理类
2. 通过为 Proxy 类指定 ClassLoader 对象和一组 interface 来创建动态代理类;
3. 通过反射机制获得动态代理类的构造函数,其唯一参数类型是调用处理器接口类型;
4. 通过构造函数创建动态代理类实例,构造时调用处理器对象作为参数被传入。
动态代理创建实例代码
基类接口
package imitate.proxy.intercepter;
public interface Dog {
void info();
void run();
}
被代理实现类
package imitate.proxy.intercepter;
public class DogImpl  implements Dog{
@Override
public void info() {
// TODO Auto-generated method stub
System.out.println( "可爱的小猎狗");
}
@Override
public void run() {
// TODO Auto-generated method stub
System.out.println( "疯狂的跑呀跑呀");
}
}
生成代理的类
package imitate.proxy.intercepter;
import java.lang.reflect.Proxy;
//根据目标对象生成一个代理对象
public class MyProxyFactory {

public static Object getProxy(Object obj)
{
//代理的处理类
ProxyHandler proxy= new ProxyHandler();
proxy.setTarget(obj);
//第一个参数用来创建动态代理的对象
//第二个参数代理的接口对象数组
//第三个参数代理包含的处理实例
//返回一个指定接口的代理类实例,该接口可以将方法调用指派到指定的调用处理程序。此方法相当于: 
return Proxy.newProxyInstance(obj. getClass.getClassLoader(),
obj.getClass().getInterfaces(), proxy);
}
}
代理 调用处理器接口
package imitate.proxy.intercepter;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;

public class ProxyHandler  implements InvocationHandler {

//需要被代理的目标对象
private Object target;
//用于设置传入目标对象的方法
public void setTarget(Object obj)
{
this.target=obj;
}

@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
// TODO Auto-generated method stub
Object result= null;
if(method.getName().equals( "info"))
{
System.out.println( "First enter here");
result=method.invoke(target, args);
System.out.println( "Last exit here");
}
else
{
System.out.println( "First other enter here");
result=method.invoke(target, args);
System.out.println( "First other enter here");
}
return result;
}

}
动态代理测试类
package imitate.proxy.intercepter;

public class TestDog {
public static void main(String[] args) {

Dog target= new DogImpl();
Dog dog= null;
//以目标对象创建代理
Object proxy=MyProxyFactory.getProxy(target);
if(proxy  instanceof Dog)
{
dog=(Dog)proxy;
}
dog.info();
}
}


本文转自 zhao_xiao_long 51CTO博客,原文链接:http://blog.51cto.com/computerdragon/1178054

相关文章
|
12月前
|
设计模式 网络协议 数据可视化
Java 设计模式之状态模式:让对象的行为随状态优雅变化
状态模式通过封装对象的状态,使行为随状态变化而改变。以订单为例,将待支付、已支付等状态独立成类,消除冗长条件判断,提升代码可维护性与扩展性,适用于状态多、转换复杂的场景。
1246 157
|
12月前
|
设计模式 Java Spring
Java 设计模式之责任链模式:优雅处理请求的艺术
责任链模式通过构建处理者链,使请求沿链传递直至被处理,实现发送者与接收者的解耦。适用于审批流程、日志处理等多级处理场景,提升系统灵活性与可扩展性。
1243 2
|
设计模式 缓存 Java
Java设计模式(二):观察者模式与装饰器模式
本文深入讲解观察者模式与装饰器模式的核心概念及实现方式,涵盖从基础理论到实战应用的全面内容。观察者模式实现对象间松耦合通信,适用于事件通知机制;装饰器模式通过组合方式动态扩展对象功能,避免子类爆炸。文章通过Java示例展示两者在GUI、IO流、Web中间件等场景的应用,并提供常见陷阱与面试高频问题解析,助你写出灵活、可维护的代码。
|
12月前
|
设计模式 算法 搜索推荐
Java 设计模式之策略模式:灵活切换算法的艺术
策略模式通过封装不同算法并实现灵活切换,将算法与使用解耦。以支付为例,微信、支付宝等支付方式作为独立策略,购物车根据选择调用对应支付逻辑,提升代码可维护性与扩展性,避免冗长条件判断,符合开闭原则。
2958 35
|
设计模式 缓存 安全
【高薪程序员必看】万字长文拆解Java并发编程!(8):设计模式-享元模式设计指南
🌟 ​大家好,我是摘星!​ 🌟今天为大家带来的是并发编程中的经典对象复用设计模式-享元模式,废话不多说让我们直接开始。
336 0
|
12月前
|
设计模式 消息中间件 传感器
Java 设计模式之观察者模式:构建松耦合的事件响应系统
观察者模式是Java中常用的行为型设计模式,用于构建松耦合的事件响应系统。当一个对象状态改变时,所有依赖它的观察者将自动收到通知并更新。该模式通过抽象耦合实现发布-订阅机制,广泛应用于GUI事件处理、消息通知、数据监控等场景,具有良好的可扩展性和维护性。
857 8
|
设计模式 安全 Java
Java设计模式(一):单例模式与工厂模式
本文详解单例模式与工厂模式的核心实现及应用,涵盖饿汉式、懒汉式、双重检查锁、工厂方法、抽象工厂等设计模式,并结合数据库连接池与支付系统实战案例,助你掌握设计模式精髓,提升代码专业性与可维护性。
|
设计模式 XML 安全
Java枚举(Enum)与设计模式应用
Java枚举不仅是类型安全的常量,还具备面向对象能力,可添加属性与方法,实现接口。通过枚举能优雅实现单例、策略、状态等设计模式,具备线程安全、序列化安全等特性,是编写高效、安全代码的利器。
|
设计模式 Java 数据库连接
【设计模式】【结构型模式】代理模式(Proxy)
一、入门 什么是代理模式? 代理模式(Proxy Pattern)是一种结构型设计模式,允许你提供一个代理对象来控制对另一个对象的访问。 代理对象在客户端和目标对象之间起到中介作用,可以在不改变目标对
502 10
|
设计模式 缓存 Java
「全网最细 + 实战源码案例」设计模式——代理模式
代理模式(Proxy Pattern)是一种结构型设计模式,通过代理对象控制对目标对象的访问并添加额外功能。它分为静态代理和动态代理,后者包括JDK动态代理和CGLIB动态代理。JDK动态代理基于接口反射生成代理类,而CGLIB通过继承目标类生成子类。代理模式适用于延迟初始化、访问控制、远程服务、日志记录和缓存等场景,优点是职责分离、符合开闭原则和提高安全性,缺点是增加系统复杂性。
546 25