代理模式
Posted 可乐淘
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了代理模式相关的知识,希望对你有一定的参考价值。
一、代理模式介绍
1、定义:为其他对象提供一种代理以控制对这个对象的访问。代理对象起到中介的作用,可去掉功能服务或增加额外的服务;
2、分类:远程代理、虚拟代理、保护代理、智能引用代理;
二、以智能引用代理为例,通过静态代理来实现代理模式
1、静态代理:代理和被代理的对象在代理之前是确定的,他们都实现相同的接口或者继承相同的抽象类。
2、引例:不使用代理模式,记录一辆车的行驶时间
/**
* 行驶的接口
*/
public interface DriveInterface
public void drive();
/**
* 普通的汽车类
*/
public class Car implements DriveInterface
@Override
public void drive()
long start = System.currentTimeMillis();
System.out.println("启动汽车");
try
Thread.sleep(new Random().nextInt(1000));
System.out.println("行驶中……");
catch (InterruptedException e)
e.printStackTrace();
long end = System.currentTimeMillis();
System.out.println("汽车停止,行驶时间是"+(end-start)+"微秒!");
/**
* 测试类
*/
public class Test
public static void main(String[] args)
Car car = new Car();
car.drive();
【运行结果】:
启动汽车
行驶中……
汽车停止,行驶时间是331微秒!
3、通过继承的方式,使用代理模式记录一辆车的行驶时间
/**
* 行驶的接口
*/
public interface DriveInterface
public void drive();
/**
* 普通的汽车类
*/
public class Car implements DriveInterface
@Override
public void drive()
try
Thread.sleep(new Random().nextInt(1000));
System.out.println("行驶中……");
catch (InterruptedException e)
e.printStackTrace();
/**
* 通过继承的方式,使用代理模式记录一辆车的行驶时间
*/
public class Car2 extends Car
@Override
public void drive()
long start = System.currentTimeMillis();
System.out.println("启动汽车");
super.drive();
long end = System.currentTimeMillis();
System.out.println("汽车停止,行驶时间是"+(end-start)+"微秒!");
/**
* 测试类
*/
public class Test
public static void main(String[] args)
Car2 car = new Car2();
car.drive();
【运行结果】:
启动汽车
行驶中……
汽车停止,行驶时间是944微秒!
4、通过聚合的方式,使用代理模式记录一辆车的行驶时间
/**
* 行驶的接口
*/
public interface DriveInterface
public void drive();
/**
* 普通的汽车类
*/
public class Car implements DriveInterface
@Override
public void drive()
try
Thread.sleep(new Random().nextInt(1000));
System.out.println("行驶中……");
catch (InterruptedException e)
e.printStackTrace();
/**
* 通过聚合的方式,使用代理模式记录一辆车的行驶时间
*/
public class Car2
private Car car;
public Car2(Car car)
this.car = car;
public void driveCar2()
long start = System.currentTimeMillis();
System.out.println("启动汽车");
car.drive();
long end = System.currentTimeMillis();
System.out.println("汽车停止,行驶时间是"+(end-start)+"微秒!");
/**
* 测试类
*/
public class Test
public static void main(String[] args)
Car car = new Car();
Car2 car2 = new Car2(car);
car2.driveCar2();
【运行结果】:
启动汽车
行驶中……
汽车停止,行驶时间是828微秒!
5、聚合方式比继承方式更好,比如,除了计算形式时间,还要计算油耗,还要计算里程,而且这几个指标还要能随时调换先后顺序。此时如果用继承的方式,就无法实现了,而聚合方式就能实现。
/**
* 行驶的接口
*/
public interface DriveInterface
public void drive();
/**
* 普通的汽车类
*/
public class Car implements DriveInterface
@Override
public void drive()
try
Thread.sleep(new Random().nextInt(1000));
System.out.println("行驶中……");
catch (InterruptedException e)
e.printStackTrace();
/**
* 记录一辆车的行驶时间的代理
*/
public class TimeProxy implements DriveInterface
private DriveInterface mDriveInterface;
public TimeProxy(DriveInterface mDriveInterface)
this.mDriveInterface = mDriveInterface;
@Override
public void drive()
long start = System.currentTimeMillis();
System.out.println("启动汽车,开始计算时间");
mDriveInterface.drive();
long end = System.currentTimeMillis();
System.out.println("汽车停止,行驶时间是"+(end-start)+"微秒!");
/**
* 记录一辆车的行驶里程的代理
*/
public class RoadProxy implements DriveInterface
private DriveInterface mDriveInterface;
public RoadProxy(DriveInterface mDriveInterface)
this.mDriveInterface = mDriveInterface;
@Override
public void drive()
int start = 0;
System.out.println("启动汽车,开始计算里程");
mDriveInterface.drive();
int end = new Random().nextInt(1000);
System.out.println("汽车停止,行驶历程是"+(end-start)+"公里!");
/**
* 测试类
*/
public class Test
public static void main(String[] args)
//先计算行驶时间,再计算行驶里程
Car car = new Car();
TimeProxy timeProxy = new TimeProxy(car);
RoadProxy roadProxy = new RoadProxy(timeProxy);
roadProxy.drive();
// //先计算行驶里程,再计算行驶时间
// Car car = new Car();
// RoadProxy roadProxy = new RoadProxy(car);
// TimeProxy timeProxy = new TimeProxy(timeProxy);
// timeProxy.drive();
【运行结果】:
启动汽车,开始计算里程
启动汽车,开始计算时间
行驶中……
汽车停止,行驶时间是520微秒!
汽车停止,行驶历程是94公里!
三、以智能引用代理为例,通过JDK动态代理来实现代理模式
动态代理涉及到两个类
(1)Interface InvocationHandler,该接口中只定义了一个抽象方法 public Object invoke(Object proxy, Method method, Object[] args),第一个参数proxy是代理类,第二个参数method是被代理的方法,第三个参数args是该方法中的参数。这个抽象方法在代理类中动态实现;
(2)Proxy:该类即动态代理类,static Object newProxyInstance(ClassLoader loader, Class[] interfaces, InvocationHandler h),第一个参数loader是类加载器,第二个参数interfaces是类的要实现的接口,第三个参数h就是InvocationHandler 。这个静态方法返回代理类的一个实例,返回后的代理类可以当作被代理类使用。
/**
* 行驶的接口
*/
public interface DriveInterface
public void drive();
/**
* 普通的汽车类
*/
public class Car implements DriveInterface
@Override
public void drive()
try
Thread.sleep(new Random().nextInt(1000));
System.out.println("行驶中……");
catch (InterruptedException e)
e.printStackTrace();
public class TimeHandler implements InvocationHandler
private Object target;
public TimeHandler(Object target)
this.target = target;
/**
* 参数:
* proxy 被代理的对象
* method 被代理对象的方法
* args 方法的参数
* 返回值:
* Object 方法的返回值
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable
long start = System.currentTimeMillis();
System.out.println("启动汽车,开始计算时间");
method.invoke(target);
long end = System.currentTimeMillis();
System.out.println("汽车停止,行驶时间是"+(end-start)+"微秒!");
return null;
/**
* 测试类
*/
public class Test
public static void main(String[] args)
Car car = new Car();
InvocationHandler h = new TimeHandler(car);
Class<?> cls = car.getClass();
/**
* loader 类加载器
* interfaces 实现接口
* h InvocationHandler
*/
DriveInterface drive = (DriveInterface)Proxy.newProxyInstance(cls.getClassLoader(), cls.getInterfaces(), h);
drive.drive();
四、以智能引用代理为例,通过cglib动态代理来实现代理模式
以上是关于代理模式的主要内容,如果未能解决你的问题,请参考以下文章