代理模式

一、代理模式介绍

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动态代理来实现代理模式





  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 7
    评论
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值