1、代理模式
代理模式的作用是:为其他对象提供一种代理以控制对这个对象的访问。在某些情况下,一个客户不想或者不能直接引用另一个对象,而代理对象可以在客户端和目标对象之间起到中介的作用。
代理的好处:
代理是一种常用的设计模式,其目的就是为其他对象提供一个代理以控制对某个对象的访问。 代理类负责为委托类预处理消息,过滤消息并转发消息,以及进行消息被委托类执行后的后 续处理。
上图的doSomething() 其实就可以做很多事情,过滤和转发!
代理模式涉及到的三个角色:
- 抽象角色:声明真实对象和代理对象的共同接口(为接口或者是抽象类)。
- 代理角色:代理对象角色内部含有对真实对象的引用,从而可以操作真实对象,同时代理对象提供与真实对象相同的接口以便在任何时刻都能够代替真实对象。同时,代理对象可以在执行真实对象操作时,附加其他的操作,相当于对真实对象进行封装。
- 真实角色:代理角色所代表的真实对象,是我们最终要引用的对象。
常见的代理有:
- 远程代理(Remote Proxy):对一个位于不同的地址空间对象提供一个局域代表对象,如RMI中的stub
- 虚拟代理(Virtual Proxy):根据需要将一个资源消耗很大或者比较复杂的对象,延迟加 载,在真正需要的时候才创建
- 保护代理(Protect or Access Proxy):控制对一个对象的访问权限。
- 智能引用(Smart Reference Proxy):提供比目标对象额外的服务和功能。
2、正常静态代理模式代码
// 抽象角色:
abstract public class Subject {
abstract public void request();
}
// 真实角色:实现了Subject的request()方法
public class RealSubject extends Subject {
public RealSubject() { }
public void request() {
System.out.println( " From real subject. " );
}
}
// 代理角色:
public class ProxySubject extends Subject {
// 以真实角色作为代理角色的属性
private Subject realSubject;
public ProxySubject(Subject realSubject) {this.realSubject = realSubject }
// 该方法封装了真实对象的request方法
public void request() {
preRequest();
realSubject.request(); // 此处执行真实对象的request方法
postRequest();
}
...
}
// 客户端调用:
RealSubject real = new RealSubject();
Subject sub = new ProxySubject(real);
Sub.request();
3、AIDL文件生成的java代码
其实AIDL文件很简单
// MyAIDLService.aidl
package com.anno.service.aidl;
import com.anno.service.data.ServiceData;
interface MyAIDLService {
/**
* 除了基本数据类型,其他类型的参数都需要标上方向类型:in(输入), out(输出), inout(输入输出)
*/
void addData(in ServiceData data);
List<ServiceData> getDataList();
}
生成的java代码使用了代理模式,会生成两个代理类,供服务端和客户端调用,服务端的onTransact方法和客户端的transact方法起到了通信和数据传输的作用。
/*
* This file is auto-generated. DO NOT MODIFY.
* Original file: F:\\CustomViews\\Channel2App\\src\\main\\aidl\\com\\anno\\service\\aidl\\MyAIDLService.aidl
*/
package com.anno.service.aidl;
public interface MyAIDLService extends android.os.IInterface {
/**
* Local-side IPC implementation stub class.
* 服务端使用的代理类
*/
public static abstract class Stub extends android.os.Binder implements com.anno.service.aidl.MyAIDLService {
private static final java.lang.String DESCRIPTOR = "com.anno.service.aidl.MyAIDLService";
/**
* Construct the stub at attach it to the interface.
*/
public Stub() {
this.attachInterface(this, DESCRIPTOR);
}
/**
* Cast an IBinder object into an com.anno.service.aidl.MyAIDLService interface,
* generating a proxy if needed.
* 返回一个代理类共客户端使用
*/
public static com.anno.service.aidl.MyAIDLService asInterface(android.os.IBinder obj) {
if ((obj == null)) {
return null;
}
android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
if (((iin != null) && (iin instanceof com.anno.service.aidl.MyAIDLService))) {
return ((com.anno.service.aidl.MyAIDLService) iin);
}
return new com.anno.service.aidl.MyAIDLService.Stub.Proxy(obj);
}
/**
* 返回与当前IBinder关联的实体对象
* @return
*/
@Override
public android.os.IBinder asBinder() {
return this;
}
/**
* 远程服务端的onTransact方法
* 这是Binder中最重要的回调方法,当客户端执行了transact方法时,
* 就会回调对应的远程Binder对象的onTransact方法。
* 其中code是用来区分当前客户端所调用的方法,data是输入参数,
* 这个参数不能为NULL,即使你不需要传递任何参数你也应该传递一个空的Parcel对象。
* reply是含有远程客户端执行接口的Parcel对象,flags是附加的执行远程操作的标志,
* 0表示正常的远程调用,1表示不需要返回值的one-way调用。
*
* @param code 唯一标识,客户端传递标识执行服务端代码
* @param data 客户端传递过来的参数
* @param reply 服务器返回回去的值
* @param flags 是否有返回值 0:有 1:没有
* @return
* @throws RemoteException 异常
*
*/
@Override
public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags) throws android.os.RemoteException {
switch (code) {
case INTERFACE_TRANSACTION: { //接收到客户端的通信请求
reply.writeString(DESCRIPTOR);
return true;
}
case TRANSACTION_addData: { //接收到客户端的不同请求
data.enforceInterface(DESCRIPTOR);
com.anno.service.data.ServiceData _arg0;
if ((0 != data.readInt())) {
_arg0 = com.anno.service.data.ServiceData.CREATOR.createFromParcel(data);
} else {
_arg0 = null;
}
this.addData(_arg0);
reply.writeNoException();
return true;
}
case TRANSACTION_getDataList: { //接收到客户端的不同请求
data.enforceInterface(DESCRIPTOR);
java.util.List<com.anno.service.data.ServiceData> _result = this.getDataList();
reply.writeNoException();
reply.writeTypedList(_result);
return true;
}
}
return super.onTransact(code, data, reply, flags);
}
/**
* 客户端使用的代理类
*/
private static class Proxy implements com.anno.service.aidl.MyAIDLService {
private android.os.IBinder mRemote;
Proxy(android.os.IBinder remote) {
mRemote = remote;
}
@Override
public android.os.IBinder asBinder() {
return mRemote;
}
public java.lang.String getInterfaceDescriptor() {
return DESCRIPTOR;
}
/**
* 除了基本数据类型,其他类型的参数都需要标上方向类型:in(输入), out(输出), inout(输入输出)
*/
@Override
public void addData(com.anno.service.data.ServiceData data) throws android.os.RemoteException {
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
try {
_data.writeInterfaceToken(DESCRIPTOR);
if ((data != null)) {
_data.writeInt(1);
data.writeToParcel(_data, 0);
} else {
_data.writeInt(0);
}
//客户端开始使用Binder向服务端发送请求
mRemote.transact(Stub.TRANSACTION_addData, _data, _reply, 0);
_reply.readException();
} finally {
_reply.recycle();
_data.recycle();
}
}
@Override
public java.util.List<com.anno.service.data.ServiceData> getDataList() throws android.os.RemoteException {
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
java.util.List<com.anno.service.data.ServiceData> _result;
try {
_data.writeInterfaceToken(DESCRIPTOR);
//remote.transact方法的参数和onTransact方法是一样的,当执行到transact方法,
// 当前线程会阻塞,并调用远程对象的onTransact方法。
// 注意parcel对象不再使用时必须调用recycle方法进行释放资源,以免造成内存泄漏。
mRemote.transact(Stub.TRANSACTION_getDataList, _data, _reply, 0);
_reply.readException();
_result = _reply.createTypedArrayList(com.anno.service.data.ServiceData.CREATOR);
} finally {
_reply.recycle();
_data.recycle();
}
return _result;
}
}
static final int TRANSACTION_addData = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
static final int TRANSACTION_getDataList = (android.os.IBinder.FIRST_CALL_TRANSACTION + 1);
}
/**
* 除了基本数据类型,其他类型的参数都需要标上方向类型:in(输入), out(输出), inout(输入输出)
*/
public void addData(com.anno.service.data.ServiceData data) throws android.os.RemoteException;
public java.util.List<com.anno.service.data.ServiceData> getDataList() throws android.os.RemoteException;
}