意图
为其他对象提供一种代理以控制对这个对象的访问。
适用性
适用代理模式常见情况:
1.远程代理(Remote Proxy)为一个对象在不同的地址空间提供局部代表;
2.虚代理(Virtual Proxy)根据需要创建开销很大的对象,比如我们从网站上下载一张大图时,可以先显示默认图,下载完成后再显示真正的图;
3.保护代理(Protection Proxy)控制对原始对象的访问,用于对象应该有不同的访问权限的时候。
4.智能指引(Smart Reference)取代了简单的指针,在访问对象时执行一些附加操作。它的典型用途包括:
1)对指向实际对象的引用计数,这样当该对象没有引用时,可以自动释放它。
2)当第一次引用一个持久对象时,将它装入内存。
3)在访问一个实际对象前,检查是否已经锁定了它,以确保其他对象不能改变它。
类图
角色介绍
Subject:抽象主题类,该类的主要职责是声明真实主题和代理的共同接口方法,该类既可以是一个抽象类,也可以是一个接口。
RealSubject:真实主题类,该类也被称为委托类或被代理类,该类定义了代理所表示的真实对象,由其执行具体的业务逻辑方法。
Proxy:代理类,该类持有一个对真实主题类的引用,在其所实现的接口方法中调用真实主题类中相应的接口方法执行,以此起到代理的作用。
生活中的示例
生活当中有很多需要别人代理的事情,比如打官司,请律师代理诉讼;打游戏,请代练等等。这里以请保姆照看小孩为例,当父母都要上班忙不过来时,需要请保姆照看小孩,给小孩穿衣服,喂饭 ,洗澡等。
类图
注:图中Parents类和BabySitter类是实现接口,要用虚线+三角箭头,但是ProcessOn上面没有虚线的选项,这里用的实线。
IWatchBaby接口:对应于Subject,定义出了共同接口方法;
Parents类: 对应于RealSubject;
BabySitter类:保姆,对应于Proxy类,它持有一个Parents的引用。
代码:
Client.java
package com.sunny.disignpattern.proxy;
/**
* @ProjectName: DesignPattern23
* @Package: com.sunny.disignpattern.proxy
* @ClassName: Client
* @Description: 客户类
* @Author: Sunny
* @CreateDate: 2020/6/25 10:18 AM:
*/
public class Client {
public static void main(String[] args) {
Parents parents = new Parents();
BabySitter babySitter = new BabySitter(parents);
babySitter.getBath();
babySitter.dress();
babySitter.feed();
}
}
IWatchBaby.java
package com.sunny.disignpattern.proxy;
/**
* @ProjectName: DesignPattern23
* @Package: com.sunny.disignpattern.proxy
* @ClassName: IWatchBaby
* @Description: 照看小孩的公共接口
* @Author: Sunny
* @CreateDate: 2020/6/25 10:13 AM:
*/
public interface IWatchBaby {
void dress();
void getBath();
void feed();
}
Parents.java
package com.sunny.disignpattern.proxy;
/**
* @ProjectName: DesignPattern23
* @Package: com.sunny.disignpattern.proxy
* @ClassName: Parents
* @Description: 父母类
* @Author: Sunny
* @CreateDate: 2020/6/25 10:13 AM:
*/
public class Parents implements IWatchBaby {
@Override
public void dress() {
System.out.println("给小孩穿衣服");
}
@Override
public void getBath() {
System.out.println("给小孩洗澡");
}
@Override
public void feed() {
System.out.println("给小孩喂饭");
}
}
BabySitter.java
package com.sunny.disignpattern.proxy;
/**
* @ProjectName: DesignPattern23
* @Package: com.sunny.disignpattern.proxy
* @ClassName: BabySitter
* @Description: 保姆类
* @Author: Sunny
* @CreateDate: 2020/6/25 10:15 AM:
*/
public class BabySitter implements IWatchBaby {
Parents parents;
public BabySitter(Parents parents) {
this.parents = parents;
}
@Override
public void dress() {
parents.dress();
}
@Override
public void getBath() {
parents.getBath();
}
@Override
public void feed() {
parents.feed();
}
}
Android源码中的示例
基于Android9.0源码:
当应用通过ActivityManager访问ActivityManagerService的接口方法时,本质上是通过IActivityManager的代理对象访问的,是一种典型的代理模式。
IActivityManger.aidl接口如下:
interface IActivityManager {
//......省略部分代码......
int startActivity(in IApplicationThread caller, in String callingPackage, in Intent intent,
in String resolvedType, in IBinder resultTo, in String resultWho, int requestCode,
int flags, in ProfilerInfo profilerInfo, in Bundle options);
//......省略部分代码......
}
接口真正的实现都在ActivityManagerService。
ActivityManagerService.java部分代码
public class ActivityManagerService extends IActivityManager.Stub
implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback {
//......省略部分代码......
@Override
public final int startActivity(IApplicationThread caller, String callingPackage,
Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,
int startFlags, ProfilerInfo profilerInfo, Bundle bOptions) {
return startActivityAsUser(caller, callingPackage, intent, resolvedType, resultTo,
resultWho, requestCode, startFlags, profilerInfo, bOptions,
UserHandle.getCallingUserId());
}
//......省略部分代码......
}
可见ActivityManagerService继承于IActivityManager.Stub-是IActivityManager.aidl 生成的java文件的内部抽象类。
在看ActivityManager.java中通过getService方法拿到IActivityManager对象。
public class ActivityManager {
//.......省略部分代码......
* @hide
*/
public static IActivityManager getService() {
return IActivityManagerSingleton.get();
}
private static final Singleton<IActivityManager> IActivityManagerSingleton =
new Singleton<IActivityManager>() {
@Override
protected IActivityManager create() {
final IBinder b = ServiceManager.getService(Context.ACTIVITY_SERVICE);
final IActivityManager am = IActivityManager.Stub.asInterface(b);
return am;
}
};
//......省略部分代码......
}
拿到IActivityManager对象后,调用IActivityManager接口就像直接调用ActivityManagerService一样。实际上,中间还有一个跨进程的操作。