Java设计模式之代理模式

代理:我的理解是目标对象不直接参与目标事件,而是将自己的引用交由代理对象,由代理对象去办目标事件,代理对象可以在做目标事件之前或者之后,可以做一些次要的事,使目标事物更加圆满。

以卖书为例,我们知道印刷厂卖书,一些书店也卖书,对于我们这种消费者来说主要是通过书店卖书,书店会提供打折或者积分的销售方式。

目标对象:印刷厂

代理对象:书店

目标卖书:卖书

次要事件:打折 积分

静态代理 :

//卖书的接口
public interface Subject {
	public void sellBook();
}
//目标类 也就是印刷厂
public class RealSubject implements Subject {

	@Override
	public void sellBook() {
		System.out.println("卖书");
	}

}

代理类,代理类中有目标类的引用

public class ProxyClazz implements Subject {
	private RealSubject realSubject;
	
	public void setRealSubject(RealSubject realSubject) {
		this.realSubject = realSubject;
	}
	
	@Override
	public void sellBook() {
		daZhe();
		realSubject.sellBook();
		jiFen();
	}
	
	//打折
	private void daZhe() {
		System.out.println("打折");
	}
	//积分
	private void jiFen() {
		System.out.println("积分");
	}

}

客户端

public class Client {
	public static void main(String[] args) {
		RealSubject realSubject = new RealSubject();
		ProxyClazz proxy = new ProxyClazz();
		proxy.setRealSubject(realSubject);
		proxy.sellBook();
	}
}

结果: 

打折
卖书
积分

 jdk动态代理:

还是以卖书为例。

看一下InvovationHandler的说明:

InvocationHandler 是代理实例的调用处理程序 实现的接口。

每个代理实例都具有一个关联的调用处理程序。对代理实例调用方法时,将对方法调用进行编码并将其指派到它的调用处理程序的 invoke 方法。

定义一个指派方法调用的调用处理程序:

public class MyInvocationHandler implements InvocationHandler {

	private RealSubject realSubject;
	
	public void setRealSubject(RealSubject realSubject) {
		this.realSubject = realSubject;
	}
	//proxy - 在其上调用方法的代理实例
	//method - 对应于在代理实例上调用的接口方法的 Method 实例。 Method 对象的声明类将是在
	//其中声明方法的接口,该接口可以是代理类赖以继承方法的代理接口的超接口。
	//args - 包含传入代理实例上方法调用的参数值的对象数组,如果接口方法不使用参数,则为 null。
	//基本类型的参数被包装在适当基本包装器类(如 java.lang.Integer 或 java.lang.Boolean)的实例中。
	@Override
	public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
		Object result = null;
		this.daZhe();
		
		//真是对象执行目标方法
		result = method.invoke(realSubject, args);
		
		this.jiFen();
		return result;
	}
	
	//打折
	private void daZhe() {
		System.out.println("打折");
	}
	//积分
	private void jiFen() {
		System.out.println("积分");
	}

}

client端: 

public class Client {
	public static void main(String[] args) {
		RealSubject realSubject = new RealSubject();
		MyInvocationHandler handler = new MyInvocationHandler();
		handler.setRealSubject(realSubject);
		//用过Proxy类得到代理对象
		//第一个参数指定代理类的类加载器
		//第二个参数是代理类与目标类实现的同一个接口列表
		//第三个参数指派方法调用的调用处理程序
		Subject proxySubject = (Subject)Proxy.newProxyInstance(realSubject.getClass().getClassLoader(), RealSubject.class.getInterfaces(), handler);
		
		proxySubject.sellBook();
	}
}

结果:

打折
卖书
积分

这里说一下jdk动态代理的缺点,代理类和目标类必须实现同一接口,在代理对象调用目标方法时,会被拦截执行调用处理程序,也就是说没有实现接口的类不能被代理。

Cglib动态代理

Cgilib也是一种代理模式,与jdk代理最大的不同就是,目标类不需要继承接口也可以被代理。

public class RealSubject {
	public void sellBook() {
		System.out.println("卖书");
	}
}
public class MyMethodInterceptor implements MethodInterceptor {

	//Object 代理对象
	//Method 被代理对象方法
	//args 方法入参
	//methodProxy 代理方法
	@Override
	public Object intercept(Object obj, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
		daZhe();
		methodProxy.invokeSuper(obj, args);
		jiFen();
		return null;
	}
	
	//打折
	private void daZhe() {
		System.out.println("打折");
	}
	//积分
	private void jiFen() {
		System.out.println("积分");
	}

}
public class Client {
	public static void main(String[] args) {
		Enhancer enhancer = new Enhancer();
		enhancer.setSuperclass(RealSubject.class);
		enhancer.setCallback(new MyMethodInterceptor());
		RealSubject proxy = (RealSubject)enhancer.create();
		proxy.sellBook();
	}
	
}
打折
卖书
积分

 

 cglib是动态的生成目标类的子类作为代理类。子类重写父类的非final方法,完成对方法的代理。

 

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值