成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

設計模式系列—命令模式

開發 前端
本篇和大家一起來學習命令模式相關內容。

模式定義

將一個請求封裝為一個對象,使發出請求的責任和執行請求的責任分割開。這樣兩者之間通過命令對象進行溝通,這樣方便將命令對象進行儲存、傳遞、調用、增加與管理。

在軟件開發系統中,常常出現“方法的請求者”與“方法的實現者”之間存在緊密的耦合關系。這不利于軟件功能的擴展與維護。例如,想對行為進行“撤銷、重做、記錄”等處理都很不方便,因此“如何將方法的請求者與方法的實現者解耦?”變得很重要,命令模式能很好地解決這個問題。

模版實現如下:

  1. package com.niuh.designpattern.command.v1; 
  2.  
  3. /** 
  4.  * <p> 
  5.  * 命令模式 
  6.  * </p> 
  7.  */ 
  8. public class CommandPattern { 
  9.     public static void main(String[] args) { 
  10.         Command cmd = new ConcreteCommand(); 
  11.         Invoker ir = new Invoker(cmd); 
  12.         System.out.println("客戶訪問調用者的call()方法..."); 
  13.         ir.call(); 
  14.     } 
  15.  
  16. //抽象命令 
  17. interface Command { 
  18.     public abstract void execute(); 
  19.  
  20. //具體命令 
  21. class ConcreteCommand implements Command { 
  22.     private Receiver receiver; 
  23.  
  24.     ConcreteCommand() { 
  25.         receiver = new Receiver(); 
  26.     } 
  27.  
  28.     public void execute() { 
  29.         receiver.action(); 
  30.     } 
  31.  
  32. //接收者 
  33. class Receiver { 
  34.     public void action() { 
  35.         System.out.println("接收者的action()方法被調用..."); 
  36.     } 
  37.  
  38. //調用者 
  39. class Invoker { 
  40.     private Command command; 
  41.  
  42.     public Invoker(Command command) { 
  43.         this.command = command; 
  44.     } 
  45.  
  46.     public void setCommand(Command command) { 
  47.         this.command = command; 
  48.     } 
  49.  
  50.     public void call() { 
  51.         System.out.println("調用者執行命令command..."); 
  52.         command.execute(); 
  53.     } 

輸出結果如下:

  1. 客戶訪問調用者的call()方法... 
  2. 調用者執行命令command... 
  3. 接收者的action()方法被調用... 

解決的問題

在軟件系統中,行為請求者與行為實現者通常是一種緊耦合的關系,但某些場合,比如需要對行為進行記錄、撤銷或重做、事務等處理時,這種無法抵御變化的緊耦合的設計就不太合適。

模式組成

 

可以將系統中的相關操作抽象成命令,使調用者與實現者相關分離,其結構如下。

實例說明

實例概況

 

結合命令模式,實現一個課程視頻的打開和關閉。

使用步驟

 

步驟1:聲明執行命令的接口,擁有執行命令的抽象方法 execute()

  1. interface Command { 
  2.     void execute(); 

步驟2:定義具體命令角色,創建打開課程鏈接 和 關閉課程連接

  1. /** 
  2.  * 打開課程鏈接 
  3.  */ 
  4. class OpenCourseVideoCommand implements Command { 
  5.  
  6.     private CourseVideo courseVideo; 
  7.  
  8.     public OpenCourseVideoCommand(CourseVideo courseVideo) { 
  9.         this.courseVideo = courseVideo; 
  10.     } 
  11.  
  12.     @Override 
  13.     public void execute() { 
  14.         courseVideo.open(); 
  15.     } 
  16.  
  17. /** 
  18.  * 關閉課程鏈接 
  19.  */ 
  20. class CloseCourseVideoCommand implements Command { 
  21.  
  22.     private CourseVideo courseVideo; 
  23.  
  24.     public CloseCourseVideoCommand(CourseVideo courseVideo) { 
  25.         this.courseVideo = courseVideo; 
  26.     } 
  27.  
  28.     @Override 
  29.     public void execute() { 
  30.         courseVideo.close(); 
  31.     } 

步驟3:定義接收者角色,執行命令功能的相關操作,是具體命令對象業務的真正實現者

  1. class CourseVideo { 
  2.  
  3.     private String name
  4.  
  5.     public CourseVideo(String name) { 
  6.         this.name = name
  7.     } 
  8.  
  9.     public void open() { 
  10.         System.out.println(this.name + "課程視頻開放。"); 
  11.     } 
  12.  
  13.     public void close() { 
  14.         System.out.println(this.name + "課程視頻關閉。"); 
  15.     } 

步驟4:創建User對象為請求的發送者,即請求者角色

  1. class User { 
  2.  
  3.     private List<Command> commands = new ArrayList<>(); 
  4.  
  5.     public void addCommand(Command command) { 
  6.         commands.add(command); 
  7.     } 
  8.  
  9.     public void executeCommands() { 
  10.         commands.forEach(Command::execute); 
  11.         commands.clear(); 
  12.     } 

步驟5:測試執行

  1. public class CommandPattern { 
  2.  
  3.     public static void main(String[] args) { 
  4.         //命令接收者 
  5.         CourseVideo courseVideo = new CourseVideo("設計模式系列"); 
  6.  
  7.         //創建命令 
  8.         OpenCourseVideoCommand openCourseVideoCommand = new OpenCourseVideoCommand(courseVideo); 
  9.         CloseCourseVideoCommand closeCourseVideoCommand = new CloseCourseVideoCommand(courseVideo); 
  10.  
  11.         //創建執行人 
  12.         User user = new User(); 
  13.  
  14.         //添加命令 
  15.         user.addCommand(openCourseVideoCommand); 
  16.         user.addCommand(closeCourseVideoCommand); 
  17.  
  18.         //執行 
  19.         user.executeCommands(); 
  20.     } 

輸出結果

  • 設計模式系列課程視頻開放。
  • 設計模式系列課程視頻關閉。

優點

  1. 降低系統的耦合度。命令模式能將調用操作的對象與實現該操作的對象解耦。
  2. 增加或刪除命令非常方便。采用命令模式增加與刪除命令不會影響其他類,它滿足“開閉原則”,對擴展比較靈活。
  3. 可以實現宏命令。命令模式可以與組合模式結合,將多個命令裝配成一個組合命令,即宏命令。
  4. 方便實現 Undo 和 Redo 操作。命令模式可以與后面介紹的備忘錄模式結合,實現命令的撤銷與恢復。

缺點

可能產生大量具體命令類。因為計對每一個具體操作都需要設計一個具體命令類,這將增加系統的復雜性。

應用場景

命令執行過程較為復雜且可能存在變化,需要對執行命令動作本身進行額外操作,此時可以考慮使用命令模式

命令模式的擴展

 

在軟件開發中,有時將命令模式與組合模式聯合使用,這就構成了宏命令模式,也叫組合命令模式。宏命令包含了一組命令,它充當了具體命令與調用者的雙重角色,執行它時將遞歸調用它所包含的所有命令,其具體結構圖如下:

模版實現如下:

  1. package com.niuh.designpattern.command.v2; 
  2.  
  3. import java.util.ArrayList; 
  4.  
  5. /** 
  6.  * <p> 
  7.  * 組合命令模式 
  8.  * </p> 
  9.  */ 
  10. public class CompositeCommandPattern { 
  11.     public static void main(String[] args) { 
  12.         AbstractCommand cmd1 = new ConcreteCommand1(); 
  13.         AbstractCommand cmd2 = new ConcreteCommand2(); 
  14.         CompositeInvoker ir = new CompositeInvoker(); 
  15.         ir.add(cmd1); 
  16.         ir.add(cmd2); 
  17.         System.out.println("客戶訪問調用者的execute()方法..."); 
  18.         ir.execute(); 
  19.     } 
  20.  
  21. //抽象命令 
  22. interface AbstractCommand { 
  23.     public abstract void execute(); 
  24.  
  25. //樹葉構件: 具體命令1 
  26. class ConcreteCommand1 implements AbstractCommand { 
  27.     private CompositeReceiver receiver; 
  28.  
  29.     ConcreteCommand1() { 
  30.         receiver = new CompositeReceiver(); 
  31.     } 
  32.  
  33.     public void execute() { 
  34.         receiver.action1(); 
  35.     } 
  36.  
  37. //樹葉構件: 具體命令2 
  38. class ConcreteCommand2 implements AbstractCommand { 
  39.     private CompositeReceiver receiver; 
  40.  
  41.     ConcreteCommand2() { 
  42.         receiver = new CompositeReceiver(); 
  43.     } 
  44.  
  45.     public void execute() { 
  46.         receiver.action2(); 
  47.     } 
  48.  
  49. //樹枝構件: 調用者 
  50. class CompositeInvoker implements AbstractCommand { 
  51.     private ArrayList<AbstractCommand> children = new ArrayList<AbstractCommand>(); 
  52.  
  53.     public void add(AbstractCommand c) { 
  54.         children.add(c); 
  55.     } 
  56.  
  57.     public void remove(AbstractCommand c) { 
  58.         children.remove(c); 
  59.     } 
  60.  
  61.     public AbstractCommand getChild(int i) { 
  62.         return children.get(i); 
  63.     } 
  64.  
  65.     public void execute() { 
  66.         for (Object obj : children) { 
  67.             ((AbstractCommand) obj).execute(); 
  68.         } 
  69.     } 
  70.  
  71. //接收者 
  72. class CompositeReceiver { 
  73.     public void action1() { 
  74.         System.out.println("接收者的action1()方法被調用..."); 
  75.     } 
  76.  
  77.     public void action2() { 
  78.         System.out.println("接收者的action2()方法被調用..."); 
  79.     } 

輸出結果如下:

  • 客戶訪問調用者的execute()方法...
  • 接收者的action1()方法被調用...
  • 接收者的action2()方法被調用...

命令模式還可以同備忘錄(Memento)模式組合使用,這樣就變成了可撤銷的命令模式

源碼中的應用

  • java.util.Timer類中scheduleXXX()方法
  • java Concurrency Executor execute() 方法
  • java.lang.reflect.Method invoke()方法
  • org.springframework.jdbc.core.JdbcTemplate
  • ......

在 JdbcTemplate 中的應用

在JdbcTemplate中命令模式的使用并沒有遵從標準的命令模式的使用,只是思想相同而已。

 

在 Spring 的 JdbcTemplate 這個類中有 query() 方法,query() 方法中定義了一個內部類 QueryStatementCallback,QueryStatementCallback 又實現了 StatementCallback 接口,另外還有其它類實現了該接口,StatementCallback 接口中又有一個抽象方法 doInStatement()。在 execute() 中又調用了 query()。

StatementCallback充當的是命令角色,JdbcTemplate即充當調用者角色,又充當接收者角色。上面的類圖只是為了方便理解,實際上,QueryStatementCallback 與 ExecuteStatementCallback是JdbcTemplate中方法的內部類,具體看源碼中的內容。

部分源碼分析

 

StatementCallback接口:

  1. public interface StatementCallback<T> { 
  2.  T doInStatement(Statement stmt) throws SQLException, DataAccessException; 

JdbcTemplate類:

  1. public class JdbcTemplate extends JdbcAccessor implements JdbcOperations { 
  2.  //相當于調用者發布的一個命令 
  3.  @Override 
  4.  public <T> List<T> query(String sql, RowMapper<T> rowMapper) throws DataAccessException { 
  5.   return query(sql, new RowMapperResultSetExtractor<T>(rowMapper)); 
  6.  } 
  7.  //命令發布后由具體的命令派給接收者進行執行 
  8.  @Override 
  9.  public <T> T query(final String sql, final ResultSetExtractor<T> rse) throws DataAccessException { 
  10.   Assert.notNull(sql, "SQL must not be null"); 
  11.   Assert.notNull(rse, "ResultSetExtractor must not be null"); 
  12.   if (logger.isDebugEnabled()) { 
  13.    logger.debug("Executing SQL query [" + sql + "]"); 
  14.   } 
  15.   //內部類,實現StatementCallback,相當于具體的命令 
  16.   class QueryStatementCallback implements StatementCallback<T>, SqlProvider { 
  17.    @Override 
  18.    public T doInStatement(Statement stmt) throws SQLException { 
  19.     ResultSet rs = null
  20.     try { 
  21.      rs = stmt.executeQuery(sql); 
  22.      ResultSet rsToUse = rs; 
  23.      if (nativeJdbcExtractor != null) { 
  24.       rsToUse = nativeJdbcExtractor.getNativeResultSet(rs); 
  25.      } 
  26.      return rse.extractData(rsToUse); 
  27.     } 
  28.     finally { 
  29.      JdbcUtils.closeResultSet(rs); 
  30.     } 
  31.    } 
  32.    @Override 
  33.    public String getSql() { 
  34.     return sql; 
  35.    } 
  36.   } 
  37.   return execute(new QueryStatementCallback()); 
  38.  } 
  39.  //相當于接收者,命令真正的執行者 
  40.  @Override 
  41.  public <T> T execute(StatementCallback<T> action) throws DataAccessException { 
  42.   Assert.notNull(action"Callback object must not be null"); 
  43.   Connection con = DataSourceUtils.getConnection(getDataSource()); 
  44.   Statement stmt = null
  45.   try { 
  46.    Connection conToUse = con; 
  47.    if (this.nativeJdbcExtractor != null && 
  48.      this.nativeJdbcExtractor.isNativeConnectionNecessaryForNativeStatements()) { 
  49.     conToUse = this.nativeJdbcExtractor.getNativeConnection(con); 
  50.    } 
  51.    stmt = conToUse.createStatement(); 
  52.    applyStatementSettings(stmt); 
  53.    Statement stmtToUse = stmt; 
  54.    if (this.nativeJdbcExtractor != null) { 
  55.     stmtToUse = this.nativeJdbcExtractor.getNativeStatement(stmt); 
  56.    } 
  57.    T result = action.doInStatement(stmtToUse); 
  58.    handleWarnings(stmt); 
  59.    return result; 
  60.   } 
  61.   catch (SQLException ex) { 
  62.    // Release Connection early, to avoid potential connection pool deadlock 
  63.    // in the case when the exception translator hasn't been initialized yet. 
  64.    JdbcUtils.closeStatement(stmt); 
  65.    stmt = null
  66.    DataSourceUtils.releaseConnection(con, getDataSource()); 
  67.    con = null
  68.    throw getExceptionTranslator().translate("StatementCallback", getSql(action), ex); 
  69.   } 
  70.   finally { 
  71.    JdbcUtils.closeStatement(stmt); 
  72.    DataSourceUtils.releaseConnection(con, getDataSource()); 
  73.   } 
  74.  } 

PS:以上代碼提交在 Github :

 

https://github.com/Niuh-Study/niuh-designpatterns.git

責任編輯:姜華 來源: 今日頭條
相關推薦

2020-11-04 08:54:54

狀態模式

2020-10-23 09:40:26

設計模式

2022-01-12 13:33:25

工廠模式設計

2020-10-20 13:33:00

建造者模式

2020-10-28 11:56:47

橋接模式

2020-11-09 08:20:33

解釋器模式

2021-10-26 00:21:19

設計模式建造者

2021-10-28 19:09:09

模式原型Java

2012-01-13 15:59:07

2020-11-05 09:38:07

中介者模式

2021-09-29 13:53:17

抽象工廠模式

2022-01-14 09:22:22

設計模式橋接

2020-10-19 09:28:00

抽象工廠模式

2020-10-21 14:29:15

原型模式

2021-06-09 08:53:34

設計模式策略模式工廠模式

2021-03-02 08:50:31

設計單例模式

2013-11-26 15:48:53

Android設計模式SDK

2023-05-04 08:47:31

命令模式抽象接口

2021-06-22 15:27:13

設計模式迭代器模式Java

2013-11-26 17:00:08

Android設計模式
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 欧美精品一区二区三区在线 | 97av视频| 特黄色一级毛片 | 亚洲国产精品激情在线观看 | 欧美一区二区三区视频在线观看 | 黄色av一区 | 久久久免费 | 日韩视频在线免费观看 | 97综合在线| 黄色网址在线免费观看 | 精品国产一区久久 | 亚洲a级 | 久久久久久久久淑女av国产精品 | 日韩一区二区三区四区五区 | 国产精品中文字幕在线观看 | www.国产| 精品国产伦一区二区三区观看说明 | 精品欧美一区二区三区久久久小说 | 日韩一区二区在线视频 | 欧美激情在线精品一区二区三区 | 亚洲一区视频在线 | 欧美日韩国产精品一区二区 | 欧美精品网站 | 午夜影院在线免费观看视频 | 99日韩| 久草在线高清 | 一级网站 | 欧美另类视频 | 国产欧美日韩在线播放 | 九九综合 | 国产黄色在线 | 色婷婷av一区二区三区软件 | 奇米视频777 | 超碰91在线 | 国产成人精品午夜 | 亚洲人成在线观看 | 日本不卡一区二区三区在线观看 | 在线欧美亚洲 | 在线观看国产视频 | 亚洲福利视频一区二区 | 成人在线免费av |