Java设计模式:代理模式

来源:互联网 发布:linux下安装make命令 编辑:程序博客网 时间:2024/05/16 10:30

静态代理:

有一个接口:
public interface UserManager {public void addUser(User user);public void updateUser(User user);public void deleteUser(User user);}
我们来实现它:
public class UserManagerImpl implements UserManager {@Overridepublic void addUser(User user) {System.out.println("UserManagerImpl.addUser");}@Overridepublic void updateUser(User user) {System.out.println("UserManagerImpl.updateUser");}@Overridepublic void deleteUser(User user) {System.out.println("UserManagerImpl.deleteUser");}}
现在我们要在方法内部增加log和捕获异常:
public class UserManagerImpl implements UserManager {@Overridepublic void addUser(User user) {System.out.println("log:start-->addUser" + user);try {System.out.println("UserManagerImpl.addUser");System.out.println("log:success-->addUser");} catch(RuntimeException e) {System.out.println("log:error-->addUser");throw new RuntimeException(e);}}@Overridepublic void updateUser(User user) {System.out.println("UserManagerImpl.updateUser");}@Overridepublic void deleteUser(User user) {System.out.println("UserManagerImpl.deleteUser");}}
但是我们提供的方法是用来执行业务的,而不是进行输出log、捕获异常的。在这里做这些工作违背了这接口的功能,所以我们创建代理来做这些工作:
public class UserManagerImplProxy implements UserManager {private UserManager userManager;public UserManagerImplProxy(UserManager userManager) {this.userManager = userManager;}@Overridepublic void addUser(User user) {System.out.println("log:start-->addUser" + user);try {userManager.addUser(user);System.out.println("log:success-->addUser");} catch(RuntimeException e) {System.out.println("log:error-->addUser");throw new RuntimeException(e);}}@Overridepublic void updateUser(User user) {}@Overridepublic void deleteUser(User user) {}}
我们创建了这样一个代理类。在它里面我们输出log、捕获异常,不会对业务代码进行污染了。但是还有问题,在addUser()中的代码还会出现在updateUser()和deleteUser()中,出现了重复的代码。现在我们来看看动态代理是怎么解决这一问题的。

动态代理:

动态代理的代理类是在运行期生成出来的。
public class LogHandler implements InvocationHandler {private Object targetObj;public Object newProxy(Object targetObj) {this.targetObj = targetObj;return Proxy.newProxyInstance(targetObj.getClass().getClassLoader(), targetObj.getClass().getInterfaces(), this);}@Overridepublic Object invoke(Object proxy, Method method, Object[] args)throws Throwable {System.out.println("log:start-->" + method.getName());for(Object arg : args) {System.out.println("log:params-->" + arg);}Object result = null;try {result = method.invoke(targetObj, args);System.out.println("log:success-->" + method.getName());}catch(RuntimeException e) {System.out.println("log:error-->" + method.getName());throw e;}return result;}}
我们不必为目标对象的每个方法都输出log。我们用newProxy()方法生成动态代理对象,并将目标对象targetObj委托给动态代理。当执行目标对象中的方法时,会调用到动态代理对象的invoke()方法(我们在用Proxy.newProxyInstance()方法创建动态代理对象时,将this传给了该对象,所以该对象中有了invoke()方法)。该方法中含有目标对象方法的方法对象method以及参数列表args,这样在动态代理对象的invoke()方法中,我们又可以来执行目标对象的方法,并可以在该方法中执行想要的操作。实现如下:
LogHandler handler = new LogHandler();UserManager userManager = (UserManager)handler.newProxy(new UserManagerImpl());userManager.addUser(new User(1, "zy"));




0 0