设计模式之代理模式——用java示范

一、前言
1、代理模式概念

为一个对象提供一个替身,以控制对这个对象的访问,即通过代理对象访问目标对象(被代理对象),这样做的好处:可以在目标对象实现的基础上,增强额外的功能操作,即扩展目标对象的功能。
被代理对象可以是远程对象、创建开销大的对象和需要安全控制的对象。

2、分类

java中的代理模式分为三种:静态代理、动态代理(JDK代理、接口代理)、Cglib代理。
其中Cglib代理有些书上也把它归为了动态代理。

二、示例
1、静态代理

在静态代理当中,不管是被代理对象(也称目标对象),还是代理对象,都需要去实现共同的接口(或者是继承共同的父类)。

优点: 在不修改目标对象功能的前提下,能够通过代理对象对目标功能进行扩展。
缺点: 因为代理对象与目标对象需要实现相同的接口,所以会有很多代理类。

UML类图如下图所示:
(其中TeacherDao是被代理对象,TeacherDaoProxy是代理对象)
在这里插入图片描述
代码

  1. ITeacherDao.java
public interface ITeacherDao 
{
	public abstract void teach();
}
  1. TeacherDao.java
public class TeacherDao implements ITeacherDao
{
	@Override
	public void teach() 
	{
		System.out.println("老师正在上课。。。。。");		
	}
}
  1. TeacherDaoProxy.java
public class TeacherDaoProxy implements ITeacherDao
{
	private ITeacherDao dao;
	public TeacherDaoProxy(ITeacherDao dao)
	{
		this.dao=dao;
	}
	@Override
	public void teach() 
	{
		System.out.println("准备上课。。。");
		dao.teach();
		System.out.println("结束上课。。。");
	}

}

  1. Client.java
public class Client 
{
	public static void main(String[] args) 
	{
		TeacherDaoProxy teacherDaoroxy=new TeacherDaoProxy(new TeacherDao());
		teacherDaoroxy.teach();
	}
}
2、动态代理(JDK代理、接口代理)

动态代理与静态代理比较明显的一个区别是,动态代理中的代理对象不需要去实现接口,仅要求目标对象(亦称被代理对象)去实现接口。

代理对象的生成是利用JDK的API,动态地在内存中构建对象。
用到的是java.lang.reflect.Proxy这个类中的一个静态方法newProxyInstance(ClassLoader loader,
Class<?>[] interfaces,
InvocationHandler h),
该方法接收三个参数,分别是:
loader - 定义代理类的类加载器
interfaces - 代理类要实现的接口列表
h - 指派方法调用的调用处理程序

UML类图如下:
在这里插入图片描述
代码:

  1. ITeacherDao.java
public interface ITeacherDao 
{
	void teach();
}
  1. TeacherDao.java
public class TeacherDao implements ITeacherDao
{
	@Override
	public void teach() 
	{
		System.out.println("教师正在上课。。。");		
	}
}
  1. ProxyFactory.java
public class ProxyFactory 
{
	private Object target;
	public ProxyFactory(Object target)
	{
		this.target=target;
	}	
	public Object getProxyInstance()
	{
		return Proxy.newProxyInstance(target.getClass().getClassLoader(),
				target.getClass().getInterfaces(), new InvocationHandler() {
					
					@Override
					public Object invoke(Object proxy, Method method, Object[] args) throws Throwable
					{
						System.out.println("开始上课。。。");
						Object object=method.invoke(target, args);
						System.out.println("结束代理。。。");
						return object;
					}
				}
				);
	}
}
  1. Client.java
public class Client 
{
	public static void main(String[] args) 
	{
		ITeacherDao dao=new TeacherDao();
		ProxyFactory factory=new ProxyFactory(dao);
		ITeacherDao instance=(ITeacherDao)factory.getProxyInstance();
		instance.teach();
	}
}

3、Cglib代理

Cglib代理与前面两种代理不同的是,目标对象不需要去实现接口,它使用目标对象的子类来实现代理,Cglib代理也称为子类代理,有些书也将其归为动态代理。

Cglib是一个强大的高性能的代码生成包,它可以在运行期扩展java类与实现java接口,被许多AOP框架使用,例如Spring AOP,实现方法拦截。

Cglib包的底层使用字节码处理框架ASM来转换字节码并生成新的类。

要想使用Cglib代理,首先得导入jar包(共4个),引入依赖。点我下载jar包 。密码:c6ca

Cglib代理的UML类图如下:
在这里插入图片描述
代码:

  1. TeacherDao.java
public class TeacherDao 
{
	public String teach()
	{
		System.out.println("老师正在授课中……Cglib代理,目标对象无需实现接口!");
		return "hello";
	}
}
  1. ProxyFactory.java
public class ProxyFactory implements MethodInterceptor
{
	private Object target;
	public ProxyFactory(Object target)
	{
		this.target=target;
	}
	public Object getProxyInstance()
	{
		Enhancer enhancer=new Enhancer();//创建一个工具类
		enhancer.setSuperclass(target.getClass());//设置父类
		enhancer.setCallback(this);//设置回调函数
		return enhancer.create();//创建子类对象,即代理对象
	}
	@Override
	public Object intercept(Object arg0, Method arg1, Object[] arg2, MethodProxy arg3) throws Throwable 
	{
		System.out.println("代理开始~");
		Object object=arg1.invoke(target, arg2);
		System.out.println("代理结束~");
		return object;
	}

}
  1. Client.java
public class Client 
{
	public static void main(String[] args) 
	{
		ProxyFactory proxyFactory=new ProxyFactory(new TeacherDao());
		TeacherDao teacherDao=(TeacherDao)proxyFactory.getProxyInstance();
		String string=teacherDao.teach();
		System.out.println("方法的返回值:"+string);		
	}
}
三、总结
  1. 静态代理中,目标对象和代理对象都需要实现接口。
  2. 动态代理中,目标对象需要实现接口。
  3. Cglib代理中,目标对象不需要实现接口。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值