代理模式-你不并知道我的存在
来源:程序员人生 发布时间:2014-11-08 08:08:17 阅读次数:2134次
代理模式是对象的结构型模式,代理模式给某1个对象提供了1个代理对象,并由代理对象控制对原对象的援用。它的特点代理类与目标类有一样的接口,并且代理类与目标类之间通常存在关联关系。含有目标类的援用。以致于代理类能够控制目标对象,替它完成它的方法:预处理消息、过滤消息、把消息转发给目标类,和事后处理消息等。
依照代理的创建时期,代理类可以分为两种:
静态代理:
UserManager接口:
public interface UserManager {
public void addUser(String userId, String userName); //添加用户方法
public String findUser(String userId); //删除用户方法
}
UserManagerImpl类:
public class UserManagerImpl implements UserManager {
//用户添加
public void addUser(String userId, String userName) {
try {
System.out.println("用户ID" + userId);
}catch(Exception e) {
e.printStackTrace();
throw new RuntimeException();
}
}
//用户查询
public String findUser(String userId) {
System.out.println("用户ID" + userId);
return "张3";
}
UserManagerImplProxy代理类:
private UserManager userManager; //含有目标类对象的援用
public UserManagerImplProxy(UserManager userManager) {
this.userManager = userManager;
}
public void addUser(String userId, String userName) {
try {
System.out.println("开始添加-->>添加用户ID" + userId);
userManager.addUser(userId, userName);
System.out.println("成功添加-->>addUser()");
}catch(Exception e) {
e.printStackTrace();
System.out.println("添加失败-->>addUser()");
}
}
public String findUser(String userId) {
return null; //此处不实现,若是实现,其方式同add方法
}
客户端调用:
public class Client {
public static void main(String[] args) {
UserManager userManager = new UserManagerImplProxy(new UserManagerImpl());
userManager.addUser("0001", "张3");
}
}
视察以上代码,可以发现每个代理类只能为1个接口服务(public UserManagerImplProxy(UserManageruserManager))。这样1来需要建立大量的代理类。并且,所有的代理操作除调用的方法不1样以外,其他的操作都1样。例如,findUser中若是实现,将重复使用System.out.println("开始添加-->>添加用户ID"+
userId); System.out.println("成功添加-->>addUser()"); System.out.println("添加失败-->>addUser()");重复的代码出现屡次对开发人员来讲是绝对不允许的,那末该怎样解决这个问题呢?最好的办法那就是通过1个代理类完玉成部的代理功能,这就触及到了动态代理。
动态代理:在程序运行时,应用反射机制动态创建而成。
代码示例:
UserManager接口:
public interface UserManager {
public void addUser(String userId, String userName);
public String findUser(String userId);
}
真正实现类:
public class UserManagerImpl implements UserManager {
public void addUser(String userId, String userName) {
try {
System.out.println("用户ID" + userId);
}catch(Exception e) {
e.printStackTrace();
throw new RuntimeException();
}
}
public String findUser(String userId) {
System.out.println("用户ID" + userId);
return "张3";
}
动态代理代理类:
public class LogHandler implements InvocationHandler {
private Object targetObject;
//根据传过来的对象生成代理
public Object newProxyInstance(Object targetObject) {
this.targetObject = targetObject;
return Proxy.newProxyInstance(targetObject.getClass().getClassLoader(),
targetObject.getClass().getInterfaces(), this); //
}
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
System.out.println("start-->>" + method.getName());
for (int i=0; i<args.length; i++) {
System.out.println(args[i]);
}
Object ret = null;
try {
//调用目标方法
ret = method.invoke(targetObject, args);
System.out.println("success-->>" + method.getName());
}catch(Exception e) {
e.printStackTrace();
System.out.println("error-->>" + method.getName());
throw e;
}
return ret;
}
}
动态代理包括1个接口和1个类:
InvocationHandler接口:
Public static Object newProxyInstance(ClassLoader loader,Class<?>[]interfaces,InvocatiocHandler h)
throws IllegalArgumentException
返回1个指定接口的代理类实例,该接口可以将方法调用指派到指定的调用途理程序。
参数:
Loader:定义代理类的类加载器
Class<?>[]interfaces:得到全部的接口
InvocationHandlerh:得到InvocationHandler接口的子类实例
Proxy类:动态的声明出1个代理对象,为何样生成出代理呢?这个类必须实现了接口才行。如果这个类没有实现接口,不能生成代理。说白了他就是根据这个接口在内存中建立出1个类。
客户端调用:
public class Client {
public static void main(String[] args) {
LogHandler logHandler = new LogHandler();
UserManager userManager = (UserManager)logHandler.newProxyInstance(new UserManagerImpl());
userManager.addUser("001","猪猪");
}
}
总结:
动态代理相对静态代理来讲更加灵活了,为何呢?例如重载和覆盖,重载属于静态的结构。当定义两个参数不1样的method方法时,我们在调用的时候,需要指定method方法的参数。也就是我们在编译的时候就指定好该调谁了。而覆盖的功能更强,由于它的方法调用不是静态的时候进行绑定,也不是说我写代码编译的时候就指定好我应当调谁。而是在运行的时候决定它是甚么类型就调谁。
正常情况下,我们需要创建很多的代理类,如果我还有其他的manager也需要完成这些功能,那末她还需要创建代理类,来完成。动态代理则不用,由于这个proxySubject这个类不需要自己创建,他在内存中创建。所以你压根就不知道代理类的存在,固然代理类的个数,也不需要你关心。
生活不易,码农辛苦
如果您觉得本网站对您的学习有所帮助,可以手机扫描二维码进行捐赠