命令模式是一個高內聚的模式,其定義如下:將一個請求封裝成一個對象,從而讓你使用不同的請求把客戶端參數化,對請求排隊或者記錄日誌,可以提供命令的撤銷和恢復功能。
命令模式的通用類圖如下:
命令模式是對命令的封裝,命令模式把發出命令的責任和執行命令的責任分開,委派給不同的對象。每一個命令都是這樣一個操作:請求一方發出要求執行一個操作,接收的一方收到請求並執行操作,命令模式允許請求方和執行方獨立。
命令模式具有下列特點:
1.類見解耦
執行者和接收者之間沒有任何依賴關係,調用者實現時只需要調用Command抽象類的execute方法就可以了,不需要知道到底是那個接收者執行。
2.擴展性高
Command的子類可以非常容易擴展,而調用者Invoker和高層次的模塊Client不產生嚴重的耦合
任何事物都不可能十全十美,命令模式的缺點就是可能會出現類膨脹的情況,就是命令類Command的子類會出現多個的情況
通用類圖的源碼如下:
/** * 抽象命令類 * */ public abstract class Command { protected abstract void execute(); }
/** * 命令的具體實現類 * */ public class ConcreteCommand extends Command { private Reciver reciver; public ConcreteCommand(Reciver reciver) { this.reciver = reciver; } /** * 命令的執行方法 * * @see com.huashao.chapter.chapter15.ch01.Command#execute() */ @Override protected void execute() { reciver.action(); } }
/** * 接收者角色 * */ public class Reciver { public void action() { System.out.println("保證完成任務"); } }
public class Invoker { private Command command; public Invoker(Command command) { this.command = command; } public void action() { this.command.execute(); } }
public class Client { public static void main(String[] args) { // 創建接收者 Reciver reciver = new Reciver(); // 創建命令 Command command = new ConcreteCommand(reciver); // 創建執行者 Invoker invoker = new Invoker(command); // 執行請求 invoker.action(); } }
最近在做一個電商結算項目,其中有這麼一個功能:整個界面就是一個查詢,不過查詢的條件有很多種,截圖如下:
看看能不能用命令模式的方式實現(使用命名模式好不好先放在一邊),那麼我們是不是就可以將每一種查詢類型看做一個命令呢
類圖如下:
代碼如下:
/** * 命令對象 * */ public class CommandVO { private String command; private String value; /** * */ public CommandVO() { super(); // TODO Auto-generated constructor stub } /** * @param command * @param value */ public CommandVO(String command, String value) { super(); this.command = command; this.value = value; } public String getCommand() { return command; } public void setCommand(String command) { this.command = command; } public String getValue() { return value; } public void setValue(String value) { this.value = value; } }
public class ResultVO { private String sequence; private String type; public String getSequence() { return sequence; } public void setSequence(String sequence) { this.sequence = sequence; } public String getType() { return type; } public void setType(String type) { this.type = type; } @Override public String toString() { // TODO Auto-generated method stub return "[查詢主鍵:" + sequence + " 交易類型:" + type + "]"; } }
/** * 命令對象的接口 * */ public interface QueryCommand { // 查詢方法 public List<ResultVO> execute(CommandVO commandVO); }
/** * 根據票號查詢 * */ public class TktNoQueryCommand implements QueryCommand { private QueryReciver reciver; public TktNoQueryCommand(QueryReciver reciver) { this.reciver = reciver; } /** * @param commandVO * @return */ @Override public List<ResultVO> execute(CommandVO commandVO) { // TODO Auto-generated method stub return reciver.tktNoQuery(commandVO); } }
/** * 根據訂單號查詢 * */ public class OrderNoQueryCommand implements QueryCommand { private QueryReciver reciver; public OrderNoQueryCommand(QueryReciver reciver) { this.reciver = reciver; } /** * @param commandVO * @return */ @Override public List<ResultVO> execute(CommandVO commandVO) { // TODO Auto-generated method stub return reciver.orderNoQuery(commandVO); } }
/** * 根據退款訂單號查詢 * */ public class RefundNoQueryCommand implements QueryCommand { private QueryReciver reciver; public RefundNoQueryCommand(QueryReciver reciver) { this.reciver = reciver; } /** * @param commandVO * @return */ @Override public List<ResultVO> execute(CommandVO commandVO) { return reciver.refundNoQuery(commandVO); } }
/** * 查詢的接收者 * */ public class QueryReciver { // 根據退款訂單號查詢 public List<ResultVO> refundNoQuery(CommandVO commandVO) { System.out.println(commandVO.getCommand()); //模擬從數據庫獲取結果 List<ResultVO> list=new ArrayList<ResultVO>(); ResultVO vo=new ResultVO(); vo.setSequence(commandVO.getValue()); vo.setType("RFD"); list.add(vo); return list; } // 根據票號查詢 public List<ResultVO> tktNoQuery(CommandVO commandVO) { System.out.println(commandVO.getCommand()); //模擬從數據庫獲取結果 List<ResultVO> list=new ArrayList<ResultVO>(); ResultVO vo=new ResultVO(); vo.setSequence(commandVO.getValue()); vo.setType("RFD"); list.add(vo); return list; } // 根據訂單號查詢 public List<ResultVO> orderNoQuery(CommandVO commandVO) { System.out.println(commandVO.getCommand()); //模擬從數據庫獲取結果 List<ResultVO> list=new ArrayList<ResultVO>(); ResultVO vo=new ResultVO(); vo.setSequence(commandVO.getValue()); vo.setType("SAL"); list.add(vo); return list; } }
public class Client { public static void main(String[] args) { // 創建接收者 QueryReciver reciver = new QueryReciver(); // 創建命令對象 CommandVO vo = new CommandVO("TktNo", "232424"); // 創建命令 QueryCommand command = null; if ("TktNo".equalsIgnoreCase(vo.getCommand())) { command = new TktNoQueryCommand(reciver); } // 創建執行者 Invoker invoker = new Invoker(); invoker.setCommand(command); List<ResultVO> list= invoker.query(vo); for(ResultVO vo2:list){ System.out.println(vo2); } } }
因爲我們用的Struts2+Spring+Hibernate的模式開始,那麼上面的類圖如何體現在這幾個框架上呢?
Invoker就是相當於我們寫的Action類,而Command類就相當於Service 那麼Reciver就相當於Dao
這樣我們就可以通過注入的方式將這些類聯繫起來