java设计模式1:代理模式

静态代理:

有一个接口:

public interface UserManager {

	public void addUser(User user);

	public void updateUser(User user);

	public void deleteUser(User user);
}

我们来实现它:

public class UserManagerImpl implements UserManager {

	@Override
	public void addUser(User user) {
		System.out.println("UserManagerImpl.addUser");
	}

	@Override
	public void updateUser(User user) {
		System.out.println("UserManagerImpl.updateUser");
	}

	@Override
	public void deleteUser(User user) {
		System.out.println("UserManagerImpl.deleteUser");
	}
}

现在我们要在方法内部增加log和捕获异常:

public class UserManagerImpl implements UserManager {

	@Override
	public 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);
		}
	}

	@Override
	public void updateUser(User user) {
		System.out.println("UserManagerImpl.updateUser");
	}

	@Override
	public 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;
	}

	@Override
	public 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);
		}
	}

	@Override
	public void updateUser(User user) {

	}

	@Override
	public 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);
	}

	@Override
	public 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"));

发表评论