設計模式之-----命令模式

今天繼續學習設計模式的命令模式,命令模式在生活中算是比較常見的,比如在《大話設計模式》中,“命令模式”一節中舉得烤羊肉串的例子,小攤販烤的羊肉串,由於沒有記錄,導致人多的時候,很容易忘記哪個顧客要的什麼,要了多少,是否給錢了,要不要辣椒,這些都很容易記混的。而在一個正式的店面中,有專門的服務員負責記錄,服務員通知後廚去烤羊肉串,顧客不必與廚師親自打交道,這就體現了一個命令模式的特點,將命令請求者與命令執行者徹底解耦,當然這只是其中一個好處。

在比如電視遙控器的例子,遙控器封裝了一系列的功能,用戶只要知道這些按鍵是幹嘛的,不需要知道內部是怎麼運作的,就可以操作電視開關,換臺等操作。

以下是官方的解釋:命令模式把一個請求或者操作封裝到一個對象中。命令模式允許系統使用不同的請求把客戶端參數化,對請求排隊或者記錄請求日誌,可以提供命令的撤銷和恢復功能。

我們舉個例子,我們都用過記事本,記事本有增加記錄,刪除記錄,撤銷操作等等,我們就用命令模式來實現這個功能,來看實現代碼

這是包結構

首先是記事本

package com.command.receiver;

/**
 * 記事本類,負責執行具體的操作
 * @author ZHENGWEI
 * @date 2015-8-10
 */
public class NotePad {

	/**
	 * 在記事本中增加一條記錄
	 */
	public void addThing(){
		System.out.println("增加一條記錄");
	}
	
	/**
	 * 在記事本中刪除一條記錄
	 */
	public void removeThing(){
		System.out.println("刪除一條記錄");
	}
	
	/**
	 * 對當前編輯進行撤銷操作
	 */
	public void backOut(){
		System.out.println("撤銷當前操作");
	}
}

然後是命令的抽象接口

package com.command.command;

/**
 * 命令的抽象接口
 * @author ZHENGWEI
 * @date 2015-8-10
 */
public interface Command {

	/**
	 * 執行命令
	 */
	public void execute();
}

具體的命令類

package com.command.concrete.command;

import com.command.command.Command;
import com.command.receiver.NotePad;

/**
 * 增加記錄的命令
 * @author ZHENGWEI
 * @date 2015-8-10
 */
public class AddThingCommand implements Command{

	//具體操作類的對象
	private NotePad notePad;

	public AddThingCommand(NotePad notePad) {
		super();
		this.notePad = notePad;
	}

	/**
	 * 增加記錄的命令執行的入口
	 */
	public void execute() {
		//調用真正的操作類來實現具體功能
		notePad.addThing();
	}

}

package com.command.concrete.command;

import com.command.command.Command;
import com.command.receiver.NotePad;

/**
 * 刪除記錄的命令
 * @author ZHENGWEI
 * @date 2015-8-10
 */
public class RemoveThingCommand implements Command{

	//具體操作類的對象
	private NotePad notePad;

	public RemoveThingCommand(NotePad notePad) {
		super();
		this.notePad = notePad;
	}

	/**
	 * 刪除記錄的命令執行的入口
	 */
	public void execute() {
		//調用真正的操作類來實現具體功能
		notePad.removeThing();
	}

}

package com.command.concrete.command;

import com.command.command.Command;
import com.command.receiver.NotePad;

/**
 * 撤銷操作的命令
 * @author ZHENGWEI
 * @date 2015-8-10
 */
public class BackOutCommand implements Command{

	//具體操作類的對象
	private NotePad notePad;

	public BackOutCommand(NotePad notePad) {
		super();
		this.notePad = notePad;
	}

	/**
	 * 撤銷操作命令執行的入口
	 */
	public void execute() {
		//調用真正的操作類來實現具體功能
		notePad.backOut();
	}

}

然後就是請求者,這裏請求者是鍵盤

package com.command.invoker;

import com.command.command.Command;

/**
 * 請求者,這裏由鍵盤扮演
 * 對於記事本而言,只有鍵盤請求它才能做出相應,如果我們對它說句話,記事本是不會有反應的
 * 所以對於記事本,真正的請求者是鍵盤,而人類是去操作鍵盤的
 * 記事本不會在意是誰敲的鍵盤,它只是負責響應鍵盤請求
 * @author ZHENGWEI
 * @date 2015-8-10
 */
public class KeyBoard {

	private Command addThingCommand;
	private Command removeThingCommand;
	private Command backOutCommand;
	
	public void setAddThingCommand(Command addThingCommand) {
		this.addThingCommand = addThingCommand;
	}
	public void setRemoveThingCommand(Command removeThingCommand) {
		this.removeThingCommand = removeThingCommand;
	}
	public void setBackOutCommand(Command backOutCommand) {
		this.backOutCommand = backOutCommand;
	}
	
	/**
	 * 增加的方法
	 */
	public void add(){
		addThingCommand.execute();
	}
	
	/**
	 * 刪除的方法
	 */
	public void remove(){
		removeThingCommand.execute();
	}
	
	/**
	 * 撤銷的方法
	 */
	public void back(){
		backOutCommand.execute();
	}
}

最後是測試類

package com.command.main;

import com.command.command.Command;
import com.command.concrete.command.AddThingCommand;
import com.command.concrete.command.BackOutCommand;
import com.command.concrete.command.RemoveThingCommand;
import com.command.invoker.KeyBoard;
import com.command.receiver.NotePad;

public class CommandMain {

	public static void main(String[] args) {
		NotePad notePad = new NotePad();
		
		Command add = new AddThingCommand(notePad);
		Command remove = new RemoveThingCommand(notePad);
		Command back = new BackOutCommand(notePad);
		
		KeyBoard keyBoard = new KeyBoard();
		keyBoard.setAddThingCommand(add);
		keyBoard.setRemoveThingCommand(remove);
		keyBoard.setBackOutCommand(back);
		
		keyBoard.add();
		keyBoard.remove();
		keyBoard.back();
	}

}

然後來看看結果


最後引用ID爲jason0539博客的總結

http://blog.csdn.net/jason0539/article/details/45110355


優點
1.降低對象之間的耦合度。
2.新的命令可以很容易地加入到系統中。
3.可以比較容易地設計一個組合命令。
4.調用同一方法實現不同的功能

缺點
使用命令模式可能會導致某些系統有過多的具體命令類。因爲針對每一個命令都需要設計一個具體命令類,因此某些系統可能需要大量具體命令類,這將影響命令模式的使用。

適用情況
1.系統需要將請求調用者和請求接收者解耦,使得調用者和接收者不直接交互。
2.系統需要在不同的時間指定請求、將請求排隊和執行請求。
3.系統需要支持命令的撤銷(Undo)操作和恢復(Redo)操作。
4.系統需要將一組操作組合在一起,即支持宏命令。


發佈了78 篇原創文章 · 獲贊 18 · 訪問量 22萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章