代理模式
- 代理模式中,委托类与代理类都实现相同的接口
- 代理类主要为委托类预处理信息、过滤信息、把消息转发给委托类,以及后续的事件处理
- 一个代理类与一个委托类关联(一一对应),代理类本身并不是实现服务/功能,而是通过调用委托类的相关方法来实现服务/功能
1.静态代理
静态代理顾名思义,很多逻辑都是写死的,是只实现单一功能的代理类
举个例子
- 代理者:ATM取款机
- 委托者:中国银行
- 用户:User
用户在ATM取钱的时候不直接与银行进行拿钱操作,而是需要通过在ATM验证身份成功之后,ATM才会让银行返回金钱进而与用户交互,简单逻辑代码如下:
//1. IMoney.class 获取金钱的接口每一个银行都实现此接口
public interface IMoney {
void getMoney();
}
//2. ATMManager.class ATM代理银行验证用户信息以及出钱给用户
public class ATMManager implements IMoney {
private IMoney money;
//用户需要把实现IMoney接口的银行传入
public void setMoneyManager(IMoney moneyManager) {
this.money = moneyManager;
}
//在代理模式里面才会真正获取金钱
@Override
public void getMoney() {
System.out.println("before GetMoney");
money.getMoney();
System.err.println("after GetMoney");
}
}
3. ChinaBank.class 银行操作类,实现Money接口,能够执行出钱操作
public class ChinaBank implements IMoney {
//此时才是真正的出钱
@Override
public void getMoney() {
System.out.println("Out Money");
}
}
4. User.class 用户类,操作ATM并且传入银行的验证信息后开始执行吐钱操作
public class User {
public static void main(String[] args) {
ATMManager atmManager = new ATMManager();
atmManager.setMoneyManager(new ChinaBank());
atmManager.getMoney();
}
}
2. 动态代理
动态代理是指能够实时生成运行时代理类,并且可以随意切换代理角色的一种管理类,从而没必要去写很多的代理类,拓展性更高
根据之前的例子,我们继续实现代码
- 代理者:ATM取款机升级版
- 委托者:任意银行
- 用户:User
本次升级了ATM,使得ATM能够取得任意银行的钱,使用动态代理的方式
- ATM管理类 BaseATMManager.class
public class BaseATMManager {
Object bank;
public BaseATMManager(Object bank) {
this.bank = bank;
}
@SuppressWarnings("unchecked")
public <T> T create(final Class<T> bankCls) {
return (T) Proxy.newProxyInstance(bankCls.getClassLoader(),
new Class<?>[]{bankCls},
new InvocationHandler() {
@Override
public Object invoke(Object o, Method method, Object[] objects) throws Throwable {
System.out.println("Before Get Money");
Object result = method.invoke(bank, objects);
System.out.println("After Get Money");
return result;
}
});
}
}
使用了内部代理的方式,通过Create方法来创建一个运行时class文件从而完成代理类的创建
- 用户操作类 User.class
ChinaBank bank = new ChinaBank();
BaseATMManager bankManager = new BaseATMManager(bank);
IMoney money = bankManager.create(IMoney.class);
money.getMoney();
只需要在需要取钱的时候创建相关的银行即可生成相关银行的代理类,从而进行统一的代理银行需要统一实现IMoney接口即可