代理模式

一.序言

本讲是设计模式系列的第一讲,在讨论代理模式之前,本人想就设计模式谈谈自己的几点浅见。
1.设计模式的理解
设计模式是前人总结的一套解决特定问题的经验。面向对象的编程,并不是类越多越好,类的划分是为了封装,但分类的基础是抽象,具有相同属性和功能的对象的抽象集合才是类。利用面向对象方法,通过封装、继承和多态将程序的耦合程度降低。用设计模式使得程序更加灵活,容易修改,并且易于复用,即所谓的可重用性强,可扩展性好,可维护性高。
2.使用了设计模式
a.复杂度增加
b.开发成本增加
c.维护成本降低
3.若干设计原则
1.找出应用中可能需要变化之处,把它们独立出来,不要和那些不需要变化的代码混在一起。
2.针对接口编程,而不是针对实现编程。
3.多用组合,少用继承。
4.类应该对扩展开放,对修改封闭。
5.要依赖抽象,不要依赖具体类。
4.代理模式
代理模式是常用的java设计模式,他的特征是代理类与委托类有同样的接口,代理类主要负责为委托类预处理消息、过滤消息、把消息转发给委托类,以及事后处理消息等。代理类与委托类之间通常会存在关联关系,一个代理类的对象与一个委托类的对象关联,代理类的对象本身并不真正实现服务,而是通过调用委托类的对象的相关方法,来提供特定的服务。
按照代理的创建时期,代理类可以分为两种。
静态代理:由程序员创建或特定工具自动生成源代码,再对其编译。在程序运行前,代理类的.class文件就已经存在了。
动态代理:在程序运行时,运用反射机制动态创建而成。

二.静态代理

1.代理模式的定义
代理模式(Proxy)为其他对象提供一种代理以控制对这个对象的访问。
2.示例

/**
 * 定义RealSubject和Proxy的共用接口
 * @author shixiangcheng
 * 2019-06-08
 */
public interface Subject {
	public void request();
}
/**
 * 定义Proxy所代表的真实实体
 * @author shixiangcheng
 * 2019-06-08
 */
public class RealSubject implements Subject {
	@Override
	public void request() {
		System.out.println("真实的请求");
	}
}
/**
 * 保存一个引用使得代理可以访问实体
 * @author shixiangcheng
 * 2019-06-08
 */
public class Proxy implements Subject {
	private RealSubject realSubject;
	public Proxy(RealSubject realSubject){
		this.realSubject = realSubject;
	}
	@Override
	public void request() {
		this.log("start");
		this.realSubject.request();
		this.log("end");
	}
	public void log(String log){
		System.out.println(log);
	}
}
/**
 * 客户端
 * @author shixiangcheng
 * 2019-06-08
 */
public class Client {
	public static void main(String[] args){
		Proxy proxy=new Proxy(new RealSubject());
		proxy.request();
	}
}

运行结果

start
真实的请求
end

3.分析
a.涉及的角色
抽象主题角色,声明了代理主题和真实主题的公共接口,使任何需要真实主体的地方都能用代理主题代替。
代理主题角色,含有真实主题的引用,从而可以在任何时候操作真实主体,代理主题通过提供和真实主体相同的接口,使它可以随时代替真实主体,代理主题通过
持有真实主体的引用,不但可以控制真实主体的创建或删除,可以在真实主题被调用前进行拦截,或在调用后进行某些操作。
真实代理对象,定义了代理角色所代表的具体对象。
b.优点:使得真实角色处理的业务更加纯粹,不再去关注一些公共的事情。公共的业务由代理来完成。公共业务发生扩展时变得更加集中和方便。
缺点:类多了,多了代理类,工作量变大了。开发效率降低了。

三.动态代理

1.动态代理
分为两类基于接口的动态代理(JDK动态代理)和基于类的动态代理(cglib)
Proxy类:提供用于创建动态代理类和实例的静态方法,它还是由这些方法创建的所有动态代理类的超类。Proxy类使得设计师能够在运行时间创建代理对象。当系统有了一个代理对象后,对源对象的方法调用会首先被分派给一个调用处理器(InvocationHandler)接口,该接口中有一个invoke()方法,程序员可以在调用处理器的invoke()方法中截获这个调用,进行额外操作。
InvocationHandler接口:代理实例的调用处理程序实现的接口。每个代理实例都具有一个关联的调用处理程序,对代理实例调用方法时,将对方法调用进行编码并将其指派到它的调用处理程序的invoke方法。
2.示例

/**
 * 定义RealSubject和Proxy的共用接口
 * @author shixiangcheng
 * 2019-06-08
 */
public interface Subject {
	public void request();
}
/**
 * 定义Proxy所代表的真实实体
 * @author shixiangcheng
 * 2019-06-08
 */
public class RealSubject implements Subject {
	@Override
	public void request() {
		System.out.println("真实的请求");
	}
}
/**
 * 代理类
 * @author shixiangcheng
 * 2019-06-08
 */
public class ProxyInvocationHandler implements InvocationHandler {
	private Object object;
	public ProxyInvocationHandler(Object object) {
		this.object = object;
	}
	/**
	 * @param proxy代理类
	 * @param method代理类的调用处理程序的方法对象
	 * @param args
	 */
	@Override
	public Object invoke(Object proxy, Method method, Object[] args)throws Throwable {
		System.out.println("方法"+method.getName()+"执行");
		//对被代理对象调用其方法method
		Object obj=method.invoke(object, args);
		return obj;
	}
}
/**
 * 客户端
 * @author shixiangcheng
 * 2019-06-08
 */
public class Client {
	public static void main(String[] args){
		RealSubject real=new RealSubject();
		ProxyInvocationHandler handler=new ProxyInvocationHandler(real);
		Subject subject=(Subject)Proxy.newProxyInstance(real.getClass().getClassLoader(),
				real.getClass().getInterfaces(),handler);
		//当调用代理的request方法时,首先会将该方法拿到,然后调用传进来的handler的invoke方法,即ProxyInvocationHandler的invoke,
		subject.request();
	}
}

执行结果

方法request执行
真实的请求

3.创建动态代理对象的步骤
a.指明一系列的接口来创建一个代理对象。
b.创建一个调用处理器(InvocationHandler)对象。
c.将这个代理指定为某个其他对象的代理对象。
d.在调用处理器的invoke方法中采取代理,一方面将调用传递给真实对象,另一方面执行各种需要做的操作。
4.动态代理的应用场景
a.测方法的执行时间。
b.在方法的开始和结束记录日志。
c.在方法开始时加一段事务的控制,在方法结束让事务提交或回滚。
d.在方法开始检查当前用户是否有权限。
5.总结
动态代理与静态代理类对照的是动态代理类,动态代理类的字节码在程序运行时由Java反射机制动态生成,无需程序员手工编写它的源代码。动态代理类不仅简化了编程工作,而且提高了软件系统的可扩展性,因为Java 反射机制可以生成任意类型的动态代理类。java.lang.reflect 包中的Proxy类和InvocationHandler 接口提供了生成动态代理类的能力。

四.代理模式的应用

1.远程代理,也就是为一个对象在不同的地址空间提供局部代表。这样可以隐藏一个对象存在于不同地址空间的事实。
2.虚拟代理是根据需要创建开销很大的对象,通过它来存放实例化需要很长时间的真实对象。(性能优化)。
3.安全代理是用来控制真实对象访问时的权限。
4.智能指引是指当调用真实的对象时,代理处理另外一些事。

五.代理设计模式优点

1.保护真实对象。
2.让真实对象职责更明确。
3.可扩展性强

编程是一门技术,更是一门艺术。学无止境,这或许才是学习设计模式的开始。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值