目录
介绍
代理模式也称为委托模式,是结构型设计模式之一,其重要性不言而喻,在我们平时的实际工作中也很常见,对于我们码农来说,最常接触的就是代理上网了,连上代理服务器地址,就可以轻松畅游世界;比如哪天中午开会太忙了,午饭可以找其他帮忙打包一下,他就是你的代理;如果和谁有矛盾了,需要打官司,找一个律师,这个律师就是你的代理,这些都是代理模式的实际例子。
定义
为其他对象提供一种代理以控制对该对象的访问。
使用场景
当无法或者不想直接访问某个对象,或者访问某个对象存在困难时可以通过一个代理对象来间接访问,为了保证客户端使用的透明性,委托对象与代理对象需要实现相同的接口。
代码实现
我们就以包工头拖欠农民工工资为例来模拟一下代理模式的伪代码,农民工M被老板拖欠工资,没钱回家过年,诉讼的整个过程分为提交申请、进行举证、开庭审理、诉讼完成四个步骤,伪代码如下:
public interface ILawsuit {
/** 提交申请 **/
void submit();
/** 进行举证 **/
void burden();
/** 开庭辩护 **/
void defend();
/** 诉讼完成 **/
void finish();
}
农民工M也是实现该接口,代码如下:
public class M implements ILawsuit {
@Override
public void submit() {
System.out.println("老板拖欠工资,特此申请仲裁");
}
@Override
public void burden() {
System.out.println("所有的证据都在这里,合同和银行流水,证据确凿");
}
@Override
public void defend() {
System.out.println("证据确凿,不需要说什么了");
}
@Override
public void finish() {
System.out.println("诉讼成功,判决老板在一周内结算工资给我");
}
}
他的情况是事实,但是法庭上所有的流程他一点也不懂,所以需要找一个律师,作为他的代理人帮他打官司,律师代码如下:
public class Lawyer implements ILawsuit {
private ILawsuit mLawsuit;
public Lawyer(ILawsuit iLawsuit) {
mLawsuit = iLawsuit;
}
@Override
public void submit() {
System.out.println("你的请求我接下了,我需要再具体了解一下你的情况");
mLawsuit.submit();
}
@Override
public void burden() {
System.out.println("你说的情况很正确,但是材料太粗糙,我来给你整理一下");
mLawsuit.burden();
}
@Override
public void defend() {
System.out.println("法庭上由我来辩护,你和我配合好");
mLawsuit.defend();
}
@Override
public void finish() {
System.out.println("老板已经给钱了,来领一下钱,顺便给我把服务费结了");
mLawsuit.finish();
}
}
无论是农民工M或者律师,都必须遵守法庭辩护的四步流程,所以他们俩都需要实现该接口,而律师作为农民工M的代理人,所以他会持有M的引用,但是根据开闭原则,我们在这里的定义必须清楚,持有的委托人的引用的定义是ILawsuit,也就是说我这个律师不是专门为你M一个人服务的,只要是实现了ILawsuit接口的委托人,我都可以接活,我的代理事务中会对委托人的请求进行处理,然后再进行下一步的动作。
测试代码如下:
public class Test {
public static void main() {
ILawsuit m = new M();
ILawsuit lawsuit = new Lawyer(m);
lawsuit.submit();
lawsuit.burden();
lawsuit.defend();
lawsuit.finish();
}
}
是不是很简单的代码就能表达清楚该思想,确实比较经典,这些概念如果单独拿文字来解,确实不是那么好理解,或者理解的不够深刻。
我们再来看看Android源码中代理模式的例子,接触最多的就是Context了,我们接触最多的Activity、Application等等都是Context对象,它们是继承了ContextWrapper类,而ContextWrapper又继承了Context类,所以它们才是Context对象。
我们可以看到ContextWrapper类中大部分方法都是调用mBase的方法中转的,而mBase对象就是真正的委托人,也就是我们的农民工,它才是真正的Context,它的实现类是ContextImpl,是在activity启动时通过attach方法传进来的,源码如下:
可以理清了吧,ContextWrapper就是律师,ContextImpl就是农民工,这就是典型的代理模式。