「デザインパターン」 デザインパターンの基本原理
「デザインパターン」 シングルトンパターン 「
デザインパターン」 ファクトリーパターン
「デザインパターン」 プロトタイプパターン 「デザインパターン」
ビルダーパターン 「デザインパターン
」 アダプターパターン 「デザインパターン」
ブリッジパターン
「デザインパターン」デコレータモード
「デザインモード」 コンポジションモード
「デザインモード」 アピアランスモード 「デザインモード」
フライウェイトモード 「デザインモード」 プロキシモード
「デザイン
モード」 テンプレートメソッドモード
「デザインモード」 コマンドモード
「デザインパターン」コマンドパターン
定義:
- コマンドモードは、リクエストをオブジェクトにカプセル化することであり、リクエストを送信する責任とリクエストを実行する責任が分離され、リクエスト送信者とリクエスト受信者の間の結合が解消され、オブジェクト間の呼び出し関係が解消されます。より柔軟に. 同時に、コマンド モードも元に戻す操作をサポートします.
コマンドモードの長所と短所:
- 利点: システムの結合を減らし、呼び出しオブジェクトを実装オブジェクトから切り離します; 柔軟な拡張、コマンドの追加または削除は、他のクラスに影響しません。また、コマンド キューを簡単に設計し、マルチスレッドを使用してキュー内のコマンドを実行できます。
- 欠点: システムに特定のコマンド クラスが多すぎて、システムの複雑さが増します。
コマンドモードの使用シナリオ:
- システムは、リクエストの発信者とリクエストの受信者を切り離して、発信者と受信者が直接対話しないようにする必要があります。
- システムはリクエストを指定し、それらをキューに入れ、異なるタイミングで実行する必要があります。
- システムは、コマンドの取り消し (元に戻す) 操作と回復 (やり直し) 操作をサポートする必要があります。
コマンドモードの役割構成:
- 抽象コマンド (Command) : コマンドのインターフェースを定義し、実行方法を宣言します。
- 具体的なコマンド: 具体的なコマンドは、コマンド インターフェイスを実装し、通常はレシーバーを保持し、
コマンドによって実行される操作を完了するためにレシーバーの関数を呼び出します。 - リアライザー/レシーバー (レシーバー)
: レシーバーは実際にコマンドを実行するオブジェクトであり、コマンドが必要とする対応する機能を実現できる限り、どのクラスもレシーバーになることができます。 - Invoker/Requester (Invoker) : コマンド オブジェクトを呼び出して要求を実行し、通常はコマンド オブジェクトを保持し、多くの
コマンド オブジェクトを保持できます。
コマンドモードの原則クラス図は次のとおりです。
事例の背景:
人生にはこんなシーンがあります。レストランに行って食事をするとき、まずウェイターがメニューを持ってきて、料理を選んだらメニューをウェイターに渡し、ウェイターが裏のキッチンにその旨を伝えます。料理を作るためのメニュー。実際、そのようなシナリオでは、コマンドモードの適用と見なすこともできます。ウェイターは、コマンドの呼び出し側として、シェフに料理を準備するように命令する責任があります.シェフはこの時点でコマンドの受信者であり、特定のコマンドは顧客の注文OrderCommandです.
リレーションシップ クラス図は次のとおりです。
Command
インターフェース:
public interface Command {
void execute();
void undo();
}
OrderCommand
親切:
public class OrderCommand implements Command{
private Chef receiver;
private Order order;
public OrderCommand(Chef receiver, Order order) {
this.receiver = receiver;
this.order = order;
}
@Override
public void execute() {
System.out.println("-------------------------");
System.out.println(order.getDiningTable() + "桌的订单:");
Set<String> keys = order.getFoodDic().keySet();
for (String key : keys) {
receiver.makeFood(order.getFoodDic().get(key), key);
}
try {
// 停顿一下模拟做饭的过程
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
Thread.currentThread().interrupt();
}
System.out.println(order.getDiningTable() + "桌的饭弄好了");
}
@Override
public void undo() {
System.out.println("--------------------------");
StringBuilder cancel = new StringBuilder();
cancel.append(order.getDiningTable()).append("桌的订单:");
Set<String> keys = order.getFoodDic().keySet();
for (String key : keys) {
cancel.append(order.getFoodDic().get(key)).append("份").append(key);
}
receiver.cancelMakeFood(cancel.toString());
}
}
Order
親切:
public class Order {
private int diningTable;
private Map<String, Integer> foodDic = new HashMap<>();
public int getDiningTable() {
return diningTable;
}
public void setDiningTable(int diningTable) {
this.diningTable = diningTable;
}
public Map<String, Integer> getFoodDic() {
return foodDic;
}
public void setFoodDic(String name, Integer num) {
foodDic.put(name, num);
}
}
Chef
親切:
public class Chef {
public void makeFood(int num, String foodName) {
System.out.println(num + "份" + foodName);
}
public void cancelMakeFood(String orderName) {
System.out.println("取消" + orderName);
}
}
Waitor
親切:
public class Waitor {
private List<Command> commands;
private List<Command> undoCommands;
public Waitor() {
commands = new ArrayList<>();
undoCommands = new ArrayList<>();
}
public void setCommand(Command cmd){
commands.add(cmd);
}
public void setUndoCommands(Command cmd) {
undoCommands.add(cmd);
}
public void orderUp() {
System.out.println("服务员:叮咚,大厨,新订单来了.......");
for (int i = 0; i < commands.size(); i++) {
Command cmd = commands.get(i);
if (cmd != null) {
cmd.execute();
}
}
}
public void cancelOrder() {
for (int i = 0; i < undoCommands.size(); i++) {
Command undoCmd = undoCommands.get(i);
if (undoCmd != null) {
undoCmd.undo();
}
}
}
}
Client
親切:
public class Client {
public static void main(String[] args) {
// 创建两个订单
Order order1 = new Order();
order1.setDiningTable(1);
order1.setFoodDic("西红柿鸡蛋面", 1);
order1.setFoodDic("小杯可乐", 1);
Order order2 = new Order();
order2.setDiningTable(2);
order2.setFoodDic("红烧排骨", 2);
order2.setFoodDic("柠檬水", 2);
// 创建接收者
Chef receiver = new Chef();
// 将订单和接收者封装成命令对象
OrderCommand cmd1 = new OrderCommand(receiver, order1);
OrderCommand cmd2 = new OrderCommand(receiver, order2);
// 创建调用者 waitor
Waitor invoker = new Waitor();
invoker.setCommand(cmd1);
invoker.setCommand(cmd2);
// 撤销订单的命令
invoker.setUndoCommands(cmd2);
invoker.orderUp();
invoker.cancelOrder();
}
}
Spring フレームワークの JdbcTemplate のソース コードでのコマンド モードの適用:
query
メソッドの戻り値の型は、コマンド インターフェイス CommandStatementCallback
です。- 内側の匿名クラスは特定のコマンド クラス
QueryStatementCallback
であり、doInStatement
メソッドを実装するコマンド レシーバーでもあります。 - コマンドの呼び出し元は
JdbcTemplate
class、コマンド インターフェイスのdoInStatement
メソッドはexecute メソッドで呼び出されます。
StatementCallback
インターフェース:
public interface StatementCallback<T> {
@Nullable
T doInStatement(Statement var1) throws SQLException, DataAccessException;
}
JdbcTemplate
親切:
public class JdbcTemplate extends JdbcAccessor implements JdbcOperations {
// ...
@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((StatementCallback)(new QueryStatementCallback()));
}
@Nullable
public <T> T execute(StatementCallback<T> action) throws DataAccessException {
Assert.notNull(action, "Callback object must not be null");
Connection con = DataSourceUtils.getConnection(this.obtainDataSource());
Statement stmt = null;
Object var11;
try {
stmt = con.createStatement();
this.applyStatementSettings(stmt);
T result = action.doInStatement(stmt);
this.handleWarnings(stmt);
var11 = result;
} catch (SQLException var9) {
String sql = getSql(action);
JdbcUtils.closeStatement(stmt);
stmt = null;
DataSourceUtils.releaseConnection(con, this.getDataSource());
con = null;
throw this.translateException("StatementCallback", sql, var9);
} finally {
JdbcUtils.closeStatement(stmt);
DataSourceUtils.releaseConnection(con, this.getDataSource());
}
return var11;
}
}