设计模式_代理模式(Proxy)

代理模式(Proxy)


代理模式是使用频率非常高的模式,定义是为其他对象提供一种代理以控制对这个对象的访问(provide a surrogate or placeholder for another object to contro access to it )。

1. 基本类图

定义一个ICar的接口,然后定义一个具体的实现类Car。增加一个驾驶员的代理类。这样的话就是说想启动汽车得通过驾驶员。由驾驶员驾驶汽车。

代码也比较简单。

定义一个接口,里面有一个run方法。

public interface ICar {
	public void run();
}

定义一个具体的实现类,实现接口里面的run方法

public class Car implements ICar {

	@Override
	public void run() {
		System.out.println("汽车启动了,速度很快");
	}

}

定义一个驾驶员类。实现run方法。这里注意:代理类所做的工作不是实现“实现类”里面的具体操作而是代理实现,什么时候可以做,什么时候不可以做。

假如:需要限制一个类的访问、限制一个资源的访问。

public class CarDriver implements ICar {
	
	private ICar car;
	
	public CarDriver(ICar _car) {
		this.car = _car;
	}
	
	public void run() {
		Random rand = new Random();
		
		if(rand.nextBoolean()){
			System.out.println("驾驶员同意启动汽车");
			car.run();
		}else{
			System.out.println("驾驶员不同意启动汽车");
		}
	}

}

调用类。这个没什么好说的。

public class Client {
	public static void main(String args[]){
		ICar car = new Car();
		ICar carAgent = new CarDriver(car);
		
		carAgent.run();
	}
}




2. 强制代理

 上面的基本类图是可以直接调用Car的。汽车没有驾驶员就直接可以自己跑了。这是不科学的,所以就有了这么一种强制代理。

强制代理比较另类,一般的都是通过代理类去找真是角色,就像我通过驾驶员去找汽车。而强制代理就比较特别了。得通过汽车去找驾驶员,你想上车先去找老司机,你不找到老司机我就不给你上车。不管你是new一个老司机,还是通过代理类都不行。这车只认开它的那个老司机。

意思就是说高层模块new了一个真实角色对象,但是返回的确是代理类的对象。

就像你想上一辆车,但是你得刷卡,卡在老司机那。所以你得先找到车,老司机在车上啊,然后就找到老司机,老司机给你卡,你上车。

这么一个访问控制可能有有点绕。绝对的访问控制,你不能通过别的任何方式调用真实角色,只能通过代理类来访问控制。类图可能与上面的没有什么区别,有一些区别我也没画上去。看代码就一切了然了。

这个是接口与一般模式没什么区别,新增了一个获取老司机的方法。

public interface ICar {
	public void run();
	public ICar getCarDriver();
}


真实角色类,这里区别就来了。新增了一个getCar()的方法这个方法主要的作用是返回一个代理类,就是这个车的老司机。而下面还有一个isProxy()方法。这个方法是判断有没有代理。到底这个老司机在不在车上呢。

public class Car implements ICar {

	private ICar car = null;
	
	@Override
	public void run() {
		if(this.isProxy())
			System.out.println("汽车启动了,速度很快");
		else
			System.out.println("请通过代理访问");
	}

	@Override
	public ICar getCarDriver() {
		this.car = new CarDriver(this);
		return this.car;
	}

	private boolean isProxy(){
		if(this.car == null)
			return false;
		else
			return true;
	}
}



代理类,这就与普通代理有区别了。这个构造方法,返回一个真实角色类。下面有一个是没有代理直接返回自己。返回null也一样。

public class CarDriver implements ICar {

	public ICar car;
	public CarDriver(ICar _car){
		this.car = _car;
	}
	
	@Override
	public void run() {
		Random rand = new Random();
		if(rand.nextBoolean()){
			System.out.println("驾驶员同意启动汽车");
			car.run();
		}else{
			System.out.println("驾驶员不同意启动汽车");
		}

	}
	public ICar getCarDriver() {
		return this;
	}

}


这里是调用类,上面的代码看的一头雾水。看这个调用类就能一目了然了,原来不过如此。

public class Client {
	public static void main(String args[]){
		ICar car = new Car();
		car.run();
		//ICar carDriver = new CarDriver(car);
		ICar carDriver = car.getCarDriver();
		carDriver.run();
	}
}


3. 动态代理(压轴大戏)

动态代理是在实现阶段不用关心代理类,而在运行阶段才指定哪一个对象。就像你先上车,上车再刷卡一样。不用找老司机了,上车你自然就看到了。动态代理是根据被代理的接口生成所有的方法。默认情况下所有的方法返回值都是空。现在AOP就是用动态代理,有兴趣可以研究下。如果有时间下一篇可以说说。

这个实现InvocationHandler接口的类的作用就是产生一个动态代理对象。InvocationHandler接口是JDK提供动态代理的接口,对被代理类的方法进行代理。

invoke方法是必须要实现的。他完成对真实方法的调用。即所有被代理的方法都由InvocationHandler接管。具体可以去看API。附上一篇感觉还不错的InvocationHandler详解

public class CarDriverIH implements InvocationHandler {
	
	//被代理的实例
	Object obj = null;
	
	public CarDriverIH(Object _obj){
		this.obj = _obj;
	}
	
	@Override
	public Object invoke(Object arg0, Method method, Object[] arg2) throws Throwable {
		Object result = method.invoke(this.obj, arg2);
		return result;
	}

}
这个是被代理类的接口。

public interface ICar {
	public void runCar();
}

被代理类,真实角色类。

public class Car implements ICar {

	@Override
	public void runCar() {
		System.out.println("汽车启动了,速度很快");
	}

}


这个就是客户端类。我们没有创建代理类,也没有实现ICar的接口。但是就实现了上面一般代理类的功能。这就是动态代理。

public class Client {
	public static void main(String args[]){
		ICar car = new Car();
		InvocationHandler handler = new CarDriverIH(car);
		ClassLoader cl = car.getClass().getClassLoader();
		//ICar carProxy = (ICar) Proxy.newProxyInstance(cl, car.getClass().getInterfaces(), handler);
		ICar carProxy = (ICar) Proxy.newProxyInstance(cl, new Class[]{ICar.class}, handler);
		carProxy.runCar();
	}
}



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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值