设计模式之命令模式

什么是命令模式

    命令模式是指将一个请求封装为一个对象,从而让我们可以用不同的请求对客户进行参数化。命令模式可以将请求者和接受者解耦,发送请求对象只需要知道如何发送即可。
    命令模式主要包含以下几个角色:
        Command(抽象命令类):一般是抽象类或者接口,声明了执行请求的方法,通过这些方法可以调用接受者的相关操作。
        ConcreteCommand(具体命令类):实现了抽象命令类中声明的方法,对应具体的接受者对象,调用了接受者对象的方法。
        Invoker(调用者):即请求发送者,通过命令对象来执行请求。
        Receiver(接受者):接收者执行与请求相关的操作,实现了请求的具体业务。

命令模式的优缺点

优点
  1. 降低了系统耦合性。
  2. 增加新的命令类,无需修改代码,符合开闭原则。
  3. 可以比较容易的设计一个命令队列。
缺点
  1. 会导致系统中存在过多的命令类。

命令模式的应用场景

  1. 需要将请求者和接收者解耦,使两者不直接交互。
  2. 需要在不同时间指定请求,将请求排队和执行请求。
  3. 支持命令的撤销和恢复操作。
  4. 需要将一组命令组合在一起的。

命令模式的案例

// 命令类接口
public interface Command {

    /**
     * 执行动作(操作)
     */
    void execute();

    /**
     * 撤销动作(操作)
     */
    void undo();

}

// 具体命令类
public class LightOffCommand implements Command {

	LightReceiver light;

	public LightOffCommand(LightReceiver light) {
		super();
		this.light = light;
	}

	@Override
	public void execute() {
		// 调用接收者的方法
		light.off();
	}

	@Override
	public void undo() {
		// 调用接收者的方法
		light.on();
	}
}

public class LightOnCommand implements Command {

    LightReceiver light;

    public LightOnCommand(LightReceiver light) {
        super();
        this.light = light;
    }

    @Override
    public void execute() {
        //调用接收者的方法
        light.on();
    }

    @Override
    public void undo() {
        //调用接收者的方法
        light.off();
    }

}

public class NoCommand implements Command {

    @Override
    public void execute() {

    }

    @Override
    public void undo() {

    }

}

// 命令接收者
public class LightReceiver {

    public void on() {
        System.out.println(" 电灯打开了.. ");
    }

    public void off() {
        System.out.println(" 电灯关闭了.. ");
    }

}

public static void main(String[] args) {
	//使用命令设计模式,完成通过遥控器,对电灯的操作

	//创建电灯的对象(接受者)
	LightReceiver lightReceiver = new LightReceiver();

	//创建电灯相关的开关命令
	LightOnCommand lightOnCommand = new LightOnCommand(lightReceiver);
	LightOffCommand lightOffCommand = new LightOffCommand(lightReceiver);

	//需要一个遥控器
	RemoteController remoteController = new RemoteController();

	//给我们的遥控器设置命令, 比如 no = 0 是电灯的开和关的操作
	remoteController.setCommand(0, lightOnCommand, lightOffCommand);

	System.out.println("--------按下灯的开按钮-----------");
	remoteController.onButtonWasPushed(0);
	System.out.println("--------按下灯的关按钮-----------");
	remoteController.offButtonWasPushed(0);
	System.out.println("--------按下撤销按钮-----------");
	remoteController.undoButtonWasPushed();
}

![在这里插入图片描述](https://img-blog.csdnimg.cn/b35c4494e2a14e83aecc6b6a47656e2b.png#pic_center)

命令模式在源码中的应用

JdbcTemplate
// 命令接口
@FunctionalInterface
public interface StatementCallback<T> {

	@Nullable
	T doInStatement(Statement stmt) throws SQLException, DataAccessException;

}

// 具体命令
public class JdbcTemplate extends JdbcAccessor implements JdbcOperations {

	@Override
	public void execute(final String sql) throws DataAccessException {
		if (logger.isDebugEnabled()) {
			logger.debug("Executing SQL statement [" + sql + "]");
		}

		/**
		 * Callback to execute the statement.
		 */
		class ExecuteStatementCallback implements StatementCallback<Object>, SqlProvider {
			@Override
			@Nullable
			public Object doInStatement(Statement stmt) throws SQLException {
				stmt.execute(sql);
				return null;
			}
			@Override
			public String getSql() {
				return sql;
			}
		}

		execute(new ExecuteStatementCallback(), true);
	}
	
	@Override
	@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 (logger.isDebugEnabled()) {
			logger.debug("Executing SQL query [" + sql + "]");
		}

		/**
		 * Callback to execute the query.
		 */
		class QueryStatementCallback implements StatementCallback<T>, SqlProvider {
			@Override
			@Nullable
			public T doInStatement(Statement stmt) throws SQLException {
				ResultSet rs = null;
				try {
					rs = stmt.executeQuery(sql);
					return rse.extractData(rs);
				}
				finally {
					JdbcUtils.closeResultSet(rs);
				}
			}
			@Override
			public String getSql() {
				return sql;
			}
		}

		return execute(new QueryStatementCallback(), true);
	}
	
	@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(obtainDataSource());
		Statement stmt = null;
		try {
			stmt = con.createStatement();
			applyStatementSettings(stmt);
			T result = action.doInStatement(stmt);
			handleWarnings(stmt);
			return result;
		}
		catch (SQLException ex) {
			// Release Connection early, to avoid potential connection pool deadlock
			// in the case when the exception translator hasn't been initialized yet.
			String sql = getSql(action);
			JdbcUtils.closeStatement(stmt);
			stmt = null;
			DataSourceUtils.releaseConnection(con, getDataSource());
			con = null;
			throw translateException("StatementCallback", sql, ex);
		}
		finally {
			if (closeResources) {
				JdbcUtils.closeStatement(stmt);
				DataSourceUtils.releaseConnection(con, getDataSource());
			}
		}
	}
	
	......
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值