命令模式是行为型设计模式之一,命令模式大概是将一系列的方法调用封装,用户只需要调用一个方法执行,那么所有这些被封装的方法就会被挨个执行调用。
命令模式的定义
将一个请求封装成一个对象,从而让用户使用不同的请求把客户端参数化;对请求排队或者记录请求日志,以及支持可撤销的操作。
命令模式的使用场景
1.需要抽象出待执行的动作,然后以参数的形式提供出来——类似于过程设计中的回调机制,而命令模式正是回调机制的一个面向对象的替代品。
2.在不同的时刻指定 、排列和执行请求。一个命令对象可以有与初始请求无关的生存期。
3.需要支持取消操作。
4.支持需改日志功能,当系统崩溃,这些修改可以重新执行。
5.需要支持事务操作。
命令模式UML图
Android源码中的命令模式
Android中关于命令模式的使用虽然不少,但是并不算是典型,很多方面的应用与其他大多数设计模式一样都有一定的变种,一个比较典型的例子是,在Android的事件机制中底层逻辑对事件的转发处理,Android的每一种事件在屏幕上产生后都会经由底层逻辑将其转换为一个NotifyArgs对象,NotifyArgs本身并无任何实现,只是定义了抽象的方法体。
事件对命令模式应用的这部分逻辑还算明朗,除了上述的命令者与请求者角色外,接收者角色则由具体的硬件驱动承担。
除了事件这块程序外,Android在对应用程序包管理的部分也有对命令模式应用的体现,PackageManagerService也是Android系统的Service之一,其主要功能是实现对应用包的解析、管理、卸载等操作,在PackageManagerService中,其对包的相关消息处理由其内部类PackageHandler承担,其将需要处理的请求对象通过消息传递给相关的方法,而对于包的安装、移动以及包大小的测量则分别分装在HandlerParams的3个具体子类中。
public class PackageManagerService extends IPackageManager.Stub
implements PackageSender {
private abstract class HandlerParams {
private static final int MAX_RETRIES = 4;
... ...抽象内部类
}
/**************************************************************************************/
private abstract class HandlerParams {
private static final int MAX_RETRIES = 4;
/**
* Number of times startCopy() has been attempted and had a non-fatal
* error.
*/
private int mRetries = 0;
/** User handle for the user requesting the information or installation. */
private final UserHandle mUser;
String traceMethod;
int traceCookie;
HandlerParams(UserHandle user) {
mUser = user;
}
UserHandle getUser() {
return mUser;
}
HandlerParams setTraceMethod(String traceMethod) {
this.traceMethod = traceMethod;
return this;
}
HandlerParams setTraceCookie(int traceCookie) {
this.traceCookie = traceCookie;
return this;
}
final boolean startCopy() {
boolean res;
try {
if (DEBUG_INSTALL) Slog.i(TAG, "startCopy " + mUser + ": " + this);
if (++mRetries > MAX_RETRIES) {
Slog.w(TAG, "Failed to invoke remote methods on default container service. Giving up");
mHandler.sendEmptyMessage(MCS_GIVE_UP);
handleServiceError();
return false;
} else {
handleStartCopy();
res = true;
}
} catch (RemoteException e) {
if (DEBUG_INSTALL) Slog.i(TAG, "Posting install MCS_RECONNECT");
mHandler.sendEmptyMessage(MCS_RECONNECT);
res = false;
}
handleReturnCode();
return res;
}
final void serviceError() {
if (DEBUG_INSTALL) Slog.i(TAG, "serviceError");
handleServiceError();
handleReturnCode();
}
abstract void handleStartCopy() throws RemoteException;
abstract void handleServiceError();
abstract void handleReturnCode();
}
/************************************************************************************/
class InstallParams extends HandlerParams {
}
}
这里结合命令模式来看,HandlerParams也是一个抽象命令者,而对于其3个则对应于各个功能不同的具体命令角色,请求者依然可以看做是由PackageManagerService承担的。
参考《Android源码设计模式》