项目地址:https://gitee.com/caochenlei/design-pattern
命令模式的介绍:
在软件开发系统中,“方法的请求者”与“方法的实现者”之间经常存在紧密的耦合关系,这不利于软件功能的扩展与维护。例如,想对方法进行“撤销、重做、记录”等处理都很不方便,因此“如何将方法的请求者与实现者解耦”变得很重要,命令模式就能很好地解决这个问题。
在现实生活中,命令模式的例子也很多。比如看电视时,我们只需要轻轻一按遥控器就能完成频道的切换,这就是命令模式,将换台请求和换台处理完全解耦了。电视机遥控器(命令发送者)通过按钮(具体命令)来遥控电视机(命令接收者)。
命令模式(Command Pattern)是一种数据驱动的设计模式,它属于行为型模式。请求以命令的形式包裹在对象中,并传给调用对象。调用对象寻找可以处理该命令的合适的对象,并把该命令传给相应的对象,该对象执行命令。
命令模式的优点:
命令模式的缺点:
命令模式的场景:
命令模式的角色:
Command
public interface Command {
//执行动作(操作)
public void execute();
//撤销动作(操作)
public void undo();
}
NoCommand
public class NoCommand implements Command {
@Override
public void execute() {
}
@Override
public void undo() {
}
}
TVOnCommand
public class TVOnCommand implements Command {
TVReceiver tv;
public TVOnCommand(TVReceiver tv) {
this.tv = tv;
}
@Override
public void execute() {
tv.on();
}
@Override
public void undo() {
tv.off();
}
}
TVOffCommand
public class TVOffCommand implements Command {
TVReceiver tv;
public TVOffCommand(TVReceiver tv) {
this.tv = tv;
}
@Override
public void execute() {
tv.off();
}
@Override
public void undo() {
tv.on();
}
}
TVReceiver
public class TVReceiver {
public void on() {
System.out.println(" 电视机打开了... ");
}
public void off() {
System.out.println(" 电视机关闭了... ");
}
}
RemoteController
public class RemoteController {
Command[] onCommands; //开命令集合
Command[] offCommands; //关命令集合
Command undoCommand; //撤销命令
public RemoteController() {
onCommands = new Command[5];
offCommands = new Command[5];
for (int i = 0; i < 5; i++) {
onCommands[i] = new NoCommand();
offCommands[i] = new NoCommand();
}
}
//设置命令按钮
public void setCommand(int no, Command onCommand, Command offCommand) {
onCommands[no] = onCommand;
offCommands[no] = offCommand;
}
//按下开按钮
public void onButtonWasPushed(int no) {
//找到你按下的开的按钮,并调用对应方法
onCommands[no].execute();
//记录这次的操作,用于撤销
undoCommand = onCommands[no];
}
//按下关按钮
public void offButtonWasPushed(int no) {
//找到你按下的关的按钮,并调用对应方法
offCommands[no].execute();
//记录这次的操作,用于撤销
undoCommand = offCommands[no];
}
//按下撤销按钮
public void undoButtonWasPushed() {
undoCommand.undo();
}
}
Client
public class Client {
public static void main(String[] args) {
//创建远程遥控器
RemoteController remoteController = new RemoteController();
//创建电视机接收者
TVReceiver tvReceiver = new TVReceiver();
TVOffCommand tvOffCommand = new TVOffCommand(tvReceiver);
TVOnCommand tvOnCommand = new TVOnCommand(tvReceiver);
remoteController.setCommand(0, tvOnCommand, tvOffCommand);
//调用电视机的操作
remoteController.onButtonWasPushed(0);
remoteController.offButtonWasPushed(0);
remoteController.undoButtonWasPushed();
}
}
电视机打开了...
电视机关闭了...
电视机打开了...
Spring 框架的 JdbcTemplate 就使用到了命令模式,不过并不是命令模式的标准实现,只是用到了命令模式的思想。
StatementCallback充当了抽象命令类。
@FunctionalInterface
public interface StatementCallback<T> {
@Nullable
T doInStatement(Statement stmt) throws SQLException, DataAccessException;
}
以下图片中是实现了StatementCallback的所有具体命令类。
这里QueryStatementCallback使用到了匿名内部类而不是单独写成一个类文件,它实现了命令接口, 同时也充当命令接收者。
@Nullable
public <T> T query(final String sql, final ResultSetExtractor<T> rse) throws DataAccessException {
Assert.notNull(sql, "SQL must not be null");
Assert.notNull(rse, "ResultSetExtractor must not be null");
if (this.logger.isDebugEnabled()) {
this.logger.debug("Executing SQL query [" + sql + "]");
}
class QueryStatementCallback implements StatementCallback<T>, SqlProvider {
QueryStatementCallback() {}
@Nullable
public T doInStatement(Statement stmt) throws SQLException {
ResultSet rs = null;
Object var3;
try {
rs = stmt.executeQuery(sql);
var3 = rse.extractData(rs);
} finally {
JdbcUtils.closeResultSet(rs);
}
return var3;
}
public String getSql() {
return sql;
}
}
return this.execute(new QueryStatementCallback(), true);
}
命令调用者是 JdbcTemplate,其中 execute(StatementCallback<T> action, boolean closeResources)
方法中,调用 action.doInStatement(stmt)
方法,不同的实现 StatementCallback 接口的对象,对应不同的 doInStatemnt 实现逻辑。
@Nullable
private <T> T execute(StatementCallback<T> action, boolean closeResources) throws DataAccessException {
Assert.notNull(action, "Callback object must not be null");
Connection con = DataSourceUtils.getConnection(this.obtainDataSource());
Statement stmt = null;
Object var12;
try {
stmt = con.createStatement();
this.applyStatementSettings(stmt);
T result = action.doInStatement(stmt);
this.handleWarnings(stmt);
var12 = result;
} catch (SQLException var10) {
String sql = getSql(action);
JdbcUtils.closeStatement(stmt);
stmt = null;
DataSourceUtils.releaseConnection(con, this.getDataSource());
con = null;
throw this.translateException("StatementCallback", sql, var10);
} finally {
if (closeResources) {
JdbcUtils.closeStatement(stmt);
DataSourceUtils.releaseConnection(con, this.getDataSource());
}
}
return var12;
}
错误描述: 在开发.net项目中,通过microsoft.ACE.oledb读取excel文件信息时,报...
上篇文章给大家介绍了 Java正则表达式匹配,替换,查找,切割的方法 ,接下来,...
DELETEFROMTablesWHEREIDNOTIN(SELECTMin(ID)FROMTablesGROUPBYName) Min的话保...
本文实例讲述了Laravel框架源码解析之反射的使用。分享给大家供大家参考,具体如...
工具:Eclipse,Oracle,smartupload.jar;语言:jsp,Java;数据存储:Oracle。...
Elasticsearch 是通过 Lucene 的倒排索引技术实现比关系型数据库更快的过滤。特...
项目中用到的一些特殊字符和图标 html代码 XML/HTML Code 复制内容到剪贴板 div ...
复制代码 代码如下: % URL="http://news.163.com/special/00011K6L/rss_newstop....
正则忽略大小写 – RegexOptions.IgnoreCase 例如: 复制代码 代码如下: Str = R...
4月11日20:30~22:00通过腾讯会议进行了第二次在线学习讨论我把学习笔记整理一下...