代理模式为另一个对象提供一个替身或占位符控制对这个对象的访问
假设现在你需要一笔贷款,那么你可以直接找银行,也可以找贷款经纪人,贷款经纪人能够提供更详细的信息、更便捷的服务。如果你的信用不够,或者想要更优惠的组合,银行可能不能让你满意。所以你需要一个贷款经纪人,一个代理(前面的都是扯蛋)。
java代码
// 银行接口
public interface Bank {
int loan();
}
// 某家银行
public class WestBank implements Bank {
@Override
public int loan() {
int count = new Random().nextInt(100);
System.out.println("loan $" + count);
return count;
}
}
// 贷款经纪人
public class MortgageBroker implements Bank {
private WestBank bank = new WestBank();
@Override
public int loan() {
System.out.println("do something for you ... ");
System.out.println("get more information");
System.out.println("get more convenient service");
System.out.println(" .... ");
return bank.loan();
}
}
// 测试类
public class Test {
public static void main(String[] args) {
new Test().test();
}
private void test() {
// 原始途径
Bank westBank = new WestBank();
westBank.loan();
// 通过贷款经纪人
Bank mortgageBroker = new MortgageBroker();
mortgageBroker.loan();
}
}
注:
使用代理模式创建代表对象,让代表对象控制某对象的访问,被代理的对象可以是远程对象、创建开销大的对象或需要安全控制的对象
接下去可以了解一下动态代理。
虚拟代理
虚拟代理经常用于创建资源消耗较大的对象,在大对象创建完成前代替大对象处理任务,大对象创建完成后调用大对象方法。
java代码
// 大对象
public class LargeObject {
// 模拟对象创建耗时
public LargeObject() {
try {
int time = new Random().nextInt(2000) + 2000;
System.out.println("please wait " + time);
Thread.sleep(time);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public void print() {
System.out.println("largeObject do something");
}
}
// 代理对象
public class LargeObjectProxy {
private static volatile LargeObject largeObject;
private static volatile boolean isFirst = true;
// 代理方法
public void print() {
// 当第一次调用时,创建对象,并且代替原始对象做一些操作
if (largeObject == null) {
System.out.println("proxy do something");
if (isFirst) {
synchronized (LargeObjectProxy.class) {
if (largeObject == null && isFirst) {
isFirst = false;
Thread thread = new Thread(new LargeObjectThread());
thread.start();
}
}
}
} else {
// 对象创建成功后直接调用原始对象
largeObject.print();
}
}
private class LargeObjectThread implements Runnable {
@Override
public void run() {
largeObject = new LargeObject();
System.out.println("get object success ... ");
}
}
}
// 测试对象
public class Test {
public static void main(String[] args) {
new Test().test();
}
private void test() {
LargeObjectProxy object = new LargeObjectProxy();
// 模拟10次调用
for (int i = 0; i < 10; i++) {
object.print();
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
注:
- 远程代理(Remote Proxy):为某个在不同的内存地址空间的对象提供局部代理,使系统可以将 Server 部分的实现隐藏,以便 Client 可以不必考虑 Server 的存在,类似于 C/S 模式(主要拦截并控制远程方法的调用,做代理防火墙之类的);
- 保护代理(Protection Proxy):是用代理控制对原始对象的访问,该类型的代理通常被用于原始对象有不同访问权限的情况;
- 智能引用(Smart Proxy):在访问原始对象时执行一些自己的附加操作并对指向原始对象的引用计数;
- 写时拷贝(克隆)代理(Copy-on-write Proxy):其实是虚拟代理的一个分支,提供了拷贝大对象的时候只有在对象真正变化后才会进行拷贝(克隆)的操作,即延迟拷贝。
代理模式需要为每个类都创建一个代理,比较繁琐。动态代理可以解决这个问题。