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

設(shè)計(jì)模式系列—命令模式

開發(fā) 前端
本篇和大家一起來學(xué)習(xí)命令模式相關(guān)內(nèi)容。

模式定義

將一個(gè)請(qǐng)求封裝為一個(gè)對(duì)象,使發(fā)出請(qǐng)求的責(zé)任和執(zhí)行請(qǐng)求的責(zé)任分割開。這樣兩者之間通過命令對(duì)象進(jìn)行溝通,這樣方便將命令對(duì)象進(jìn)行儲(chǔ)存、傳遞、調(diào)用、增加與管理。

在軟件開發(fā)系統(tǒng)中,常常出現(xiàn)“方法的請(qǐng)求者”與“方法的實(shí)現(xiàn)者”之間存在緊密的耦合關(guān)系。這不利于軟件功能的擴(kuò)展與維護(hù)。例如,想對(duì)行為進(jìn)行“撤銷、重做、記錄”等處理都很不方便,因此“如何將方法的請(qǐng)求者與方法的實(shí)現(xiàn)者解耦?”變得很重要,命令模式能很好地解決這個(gè)問題。

模版實(shí)現(xiàn)如下:

  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("客戶訪問調(diào)用者的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()方法被調(diào)用..."); 
  36.     } 
  37.  
  38. //調(diào)用者 
  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("調(diào)用者執(zhí)行命令command..."); 
  52.         command.execute(); 
  53.     } 

輸出結(jié)果如下:

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

解決的問題

在軟件系統(tǒng)中,行為請(qǐng)求者與行為實(shí)現(xiàn)者通常是一種緊耦合的關(guān)系,但某些場(chǎng)合,比如需要對(duì)行為進(jìn)行記錄、撤銷或重做、事務(wù)等處理時(shí),這種無法抵御變化的緊耦合的設(shè)計(jì)就不太合適。

模式組成

 

可以將系統(tǒng)中的相關(guān)操作抽象成命令,使調(diào)用者與實(shí)現(xiàn)者相關(guān)分離,其結(jié)構(gòu)如下。

實(shí)例說明

實(shí)例概況

 

結(jié)合命令模式,實(shí)現(xiàn)一個(gè)課程視頻的打開和關(guān)閉。

使用步驟

 

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

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

步驟2:定義具體命令角色,創(chuàng)建打開課程鏈接 和 關(guān)閉課程連接

  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.  * 關(guān)閉課程鏈接 
  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:定義接收者角色,執(zhí)行命令功能的相關(guān)操作,是具體命令對(duì)象業(yè)務(wù)的真正實(shí)現(xiàn)者

  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 + "課程視頻關(guān)閉。"); 
  15.     } 

步驟4:創(chuàng)建User對(duì)象為請(qǐng)求的發(fā)送者,即請(qǐng)求者角色

  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:測(cè)試執(zhí)行

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

輸出結(jié)果

  • 設(shè)計(jì)模式系列課程視頻開放。
  • 設(shè)計(jì)模式系列課程視頻關(guān)閉。

優(yōu)點(diǎn)

  1. 降低系統(tǒng)的耦合度。命令模式能將調(diào)用操作的對(duì)象與實(shí)現(xiàn)該操作的對(duì)象解耦。
  2. 增加或刪除命令非常方便。采用命令模式增加與刪除命令不會(huì)影響其他類,它滿足“開閉原則”,對(duì)擴(kuò)展比較靈活。
  3. 可以實(shí)現(xiàn)宏命令。命令模式可以與組合模式結(jié)合,將多個(gè)命令裝配成一個(gè)組合命令,即宏命令。
  4. 方便實(shí)現(xiàn) Undo 和 Redo 操作。命令模式可以與后面介紹的備忘錄模式結(jié)合,實(shí)現(xiàn)命令的撤銷與恢復(fù)。

缺點(diǎn)

可能產(chǎn)生大量具體命令類。因?yàn)橛?jì)對(duì)每一個(gè)具體操作都需要設(shè)計(jì)一個(gè)具體命令類,這將增加系統(tǒng)的復(fù)雜性。

應(yīng)用場(chǎng)景

命令執(zhí)行過程較為復(fù)雜且可能存在變化,需要對(duì)執(zhí)行命令動(dòng)作本身進(jìn)行額外操作,此時(shí)可以考慮使用命令模式

命令模式的擴(kuò)展

 

在軟件開發(fā)中,有時(shí)將命令模式與組合模式聯(lián)合使用,這就構(gòu)成了宏命令模式,也叫組合命令模式。宏命令包含了一組命令,它充當(dāng)了具體命令與調(diào)用者的雙重角色,執(zhí)行它時(shí)將遞歸調(diào)用它所包含的所有命令,其具體結(jié)構(gòu)圖如下:

模版實(shí)現(xiàn)如下:

  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("客戶訪問調(diào)用者的execute()方法..."); 
  18.         ir.execute(); 
  19.     } 
  20.  
  21. //抽象命令 
  22. interface AbstractCommand { 
  23.     public abstract void execute(); 
  24.  
  25. //樹葉構(gòu)件: 具體命令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. //樹葉構(gòu)件: 具體命令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. //樹枝構(gòu)件: 調(diào)用者 
  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()方法被調(diào)用..."); 
  75.     } 
  76.  
  77.     public void action2() { 
  78.         System.out.println("接收者的action2()方法被調(diào)用..."); 
  79.     } 

輸出結(jié)果如下:

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

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

源碼中的應(yīng)用

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

在 JdbcTemplate 中的應(yīng)用

在JdbcTemplate中命令模式的使用并沒有遵從標(biāo)準(zhǔn)的命令模式的使用,只是思想相同而已。

 

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

StatementCallback充當(dāng)?shù)氖敲罱巧琂dbcTemplate即充當(dāng)調(diào)用者角色,又充當(dāng)接收者角色。上面的類圖只是為了方便理解,實(shí)際上,QueryStatementCallback 與 ExecuteStatementCallback是JdbcTemplate中方法的內(nèi)部類,具體看源碼中的內(nèi)容。

部分源碼分析

 

StatementCallback接口:

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

JdbcTemplate類:

  1. public class JdbcTemplate extends JdbcAccessor implements JdbcOperations { 
  2.  //相當(dāng)于調(diào)用者發(fā)布的一個(gè)命令 
  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.  //命令發(fā)布后由具體的命令派給接收者進(jìn)行執(zhí)行 
  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.   //內(nèi)部類,實(shí)現(xiàn)StatementCallback,相當(dāng)于具體的命令 
  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.  //相當(dāng)于接收者,命令真正的執(zhí)行者 
  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

責(zé)任編輯:姜華 來源: 今日頭條
相關(guān)推薦

2022-01-12 13:33:25

工廠模式設(shè)計(jì)

2020-11-04 08:54:54

狀態(tài)模式

2020-10-23 09:40:26

設(shè)計(jì)模式

2021-09-29 13:53:17

抽象工廠模式

2022-01-14 09:22:22

設(shè)計(jì)模式橋接

2020-10-19 09:28:00

抽象工廠模式

2020-10-21 14:29:15

原型模式

2021-03-02 08:50:31

設(shè)計(jì)單例模式

2013-11-26 15:48:53

Android設(shè)計(jì)模式SDK

2021-06-09 08:53:34

設(shè)計(jì)模式策略模式工廠模式

2020-10-28 11:56:47

橋接模式

2020-11-09 08:20:33

解釋器模式

2021-10-28 19:09:09

模式原型Java

2012-01-13 15:59:07

2020-11-05 09:38:07

中介者模式

2021-10-26 00:21:19

設(shè)計(jì)模式建造者

2020-10-20 13:33:00

建造者模式

2023-05-04 08:47:31

命令模式抽象接口

2020-10-25 08:56:21

適配器模式

2021-03-05 07:57:41

設(shè)計(jì)模式橋接
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)

主站蜘蛛池模板: 福利网址| 欧美精品综合在线 | 日韩精品一区二区三区在线观看 | 精品视频一区二区三区在线观看 | 欧美日韩国产一区二区 | 中文字幕视频在线 | 一区二区福利视频 | 成人在线观看免费视频 | 日本欧美在线视频 | 国产精品一级 | 天堂免费看片 | 91久久精品国产91久久 | 久久精品免费观看 | 亚洲精品美女视频 | 亚洲视频一区在线观看 | 日韩一区二区三区在线视频 | www.色综合| 国产精品免费播放 | 久久午夜国产精品www忘忧草 | 91色视频在线观看 | 久精品久久 | 欧美一区二区三区在线观看 | 国产精品免费一区二区三区四区 | 日韩免费成人av | 亚洲一区不卡 | 国产精品美女久久久久久久久久久 | 日韩欧美一区二区三区 | 日韩一区二区三区精品 | 欧美不卡网站 | k8久久久一区二区三区 | 在线一级片| 精品久久久久国产 | 成人在线视频网址 | 国产 欧美 日韩 一区 | 99精品一区二区 | 国产有码 | 国产视频一视频二 | 亚洲精品成人av久久 | 亚洲色图图片 | 亚洲www | 伊人免费视频二 |