面試必知必會之設計模式:命令模式 Command Pattern

命令模式包括四種角色:

接收者(Receiver):接收者是一個類的實例,該實例負責執行與請求相關的操作。

命令(Command)接口:命令是一個接口,規定了用來封裝請求的若干個方法。

具體命令(ConcreteCommand):具體命令是實現命令接口的實例。

請求者(Invoker):請求者是一個包含Command接口變量的類的實例。請求者中的Command接口的變量可以存放任何具體命令的引用。

UML類圖:

簡單實現代碼:

package 命令模式;
/**
 * 
 * @author 11659
 * 2020年2月18日
 */
class Invoker {
    Command command;
    public void setCommand(Command command) {
    	this.command=command;
    }
    public Command getCommand() {
		return command;
	}
	public void executeCommand() {
    	command.excute();
    }
}

 

package 命令模式;

public interface Command {
    abstract void excute();
}
package 命令模式;

public class ConcreteCommand implements Command {
	Receiver receiver; 
	ConcreteCommand(Receiver receiver){
		this.receiver=receiver;
	}
	@Override
	public void excute() {
		// TODO Auto-generated method stub
		System.out.println("命令已傳達");
		receiver.action();
	}
}

 

package 命令模式;

class Receiver {
	public void action() {
		System.out.println("命令已執行");
	}
}
package 命令模式;

public class Test {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Receiver receiver=new Receiver();//創建接收者
		Command command=new ConcreteCommand(receiver);//創建具體命令並指定接收者
		Invoker invoker= new Invoker();//創建請求者
		invoker.setCommand(command);
		invoker.executeCommand();
		
	}

}

 運行:

命令模式的優點:

  • 低耦合:即請求者不包含接收者的引用,不直接交互。
  • 滿足開-閉原則:如果增加具體命令和具體命令的接收者,不需要修改請求者,反之亦然。
  • 由於請求者的請求被封裝到了具體命令中,那麼就可以將具體命令保存到持久化的媒介中。在需要的時候,可重新執行,或者撤銷這個具體命令。
  • 使用命令模式可以對請求者的請求進行排隊。每個請求都各自對應一個具體命令,因此可按照順序執行這些具體命令。

應用場景一:模擬日誌記錄,撤銷操作

代碼如下:

package 場景一撤銷操作;
import java.io.*;
/**
 * 
 * @author 11659
 * 2020年2月18日
 * 接受者
 */
public class MakeDir {
  public void makeDir(String name) {
	  System.out.println("創建文件夾"+name);
	  File dir=new File(name);
	  dir.mkdir();
  }
  public void deleteDir(String name) {
	  System.out.println("刪除文件夾"+name);
	  File dir=new File(name);
	  dir.delete();
 }
}

 

package 場景一撤銷操作;

public interface Command {
	public abstract void execute(String name);
	public abstract void undo();
}
package 場景一撤銷操作;

import java.util.ArrayList;

public class ConcreteCommand implements Command{
    ArrayList<String>  dirNameList;
    MakeDir makedir;
	public ConcreteCommand(MakeDir makeDir) {
		dirNameList=new ArrayList<String>();
		this.makedir=makeDir;
		// TODO Auto-generated constructor stub
	}

	@Override
	public void execute(String name) {
		// TODO Auto-generated method stub
		makedir.makeDir(name);
		dirNameList.add(name);
	}
	@Override
	public void undo() {
		// TODO Auto-generated method stub
		if(dirNameList.size()>0) {
			int m=dirNameList.size();
			String str=dirNameList.get(m-1);
			makedir.deleteDir(str);
			dirNameList.remove(m-1);	
		}else {
			System.out.println("沒有需要撤銷的操作");
		}
	}

}
package 場景一撤銷操作;

public class RequestMakedir {
	Command command;
	public void SetCommand(Command command) {
		this.command=command;
	}
   public void startExcuteCommand(String name) {
	   command.execute(name);
   }
   public void undoCommand() {
	   command.undo();
   }
}
package 場景一撤銷操作;

public class Test {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		//創建請求者
		RequestMakedir rmd=new RequestMakedir();
		//創建接收者
		MakeDir md=new MakeDir();
		//創建具體命令並指定接收者
		Command command=new ConcreteCommand(md);
		//爲請求者註冊具體命令
		rmd.SetCommand(command);
		//執行命令
		rmd.startExcuteCommand("1");
		rmd.startExcuteCommand("2");
		rmd.startExcuteCommand("3");
		//撤銷命令
		rmd.undoCommand();
		rmd.undoCommand();
		rmd.undoCommand();
		rmd.undoCommand();
		}

}

運行效果:

應用場景二:宏操作

請求者可以請求只輸出英文字母表、俄文字母表或1~n之間的偶數也可以請求都輸出。

代碼實現:

package 場景二宏命令;
/**
 * 
 * @author 11659
 * 2020年2月18日
 */
public class PrintLetter {
    public void  printEnglish() {
    	for(char c='a';c<='z';c++) {
    		System.out.print(" "+c);
    	}
    }
    public void printRussian() {
    	for(char c='a';c<='я';c++) {
    		System.out.print(" "+c);
    	}
    }
}
package 場景二宏命令;

public class PrintNumber {
   int n;
   PrintNumber(int n){
	   this.n=n;
   }
   public void printEvenNumber() {
	   for(int m=1;m<=n;m++) {
		   if(m%2==0) {
			   System.out.print(""+m);
		   }
	   }
   }
}
package 場景二宏命令;

public class PrintEnglishCommand implements 場景二宏命令.Command {
    PrintLetter letter;
	public PrintEnglishCommand(PrintLetter letter) {
	    this.letter=letter;
		// TODO Auto-generated constructor stub
	}
	@Override
	public void execute() {
		// TODO Auto-generated method stub
		letter.printEnglish();
	}


}
package 場景二宏命令;


public class PrintEvenNumber implements 場景二宏命令.Command {
	PrintNumber printnumber;
	public PrintEvenNumber(PrintNumber number) {
		this.printnumber=number;
		// TODO Auto-generated constructor stub
	}
	@Override
	public void execute() {
		// TODO Auto-generated method stub
		printnumber.printEvenNumber();
	}



}
package 場景二宏命令;

import java.util.ArrayList;
public class MacroCommand implements 場景二宏命令.Command {
    ArrayList<場景二宏命令.Command> commandList;
    MacroCommand(ArrayList<場景二宏命令.Command> list){
    	this.commandList=list;
    }
	@Override
	public void execute() {
		// TODO Auto-generated method stub
		for(int i=0;i<commandList.size();i++) {
			Command command=commandList.get(i);
			command.execute();
		}

	}

}
package 場景二宏命令;

public class PrintRussianCommand implements Command{
    PrintLetter printletter;
	public PrintRussianCommand(PrintLetter letter) {
		this.printletter=letter;
		// TODO Auto-generated constructor stub
	}

	@Override
	public void execute() {
		// TODO Auto-generated method stub
		printletter.printRussian();
	}

  
}
package 場景二宏命令;

public class RequestPerson {
	Command command;
	public void setCommand(Command command) {
		this.command=command;
	}
	public void startExcuteCommand() {
		command.execute();
	}
}
package 場景二宏命令;

import java.util.ArrayList;

public class Test {
 public static void main(String[] args) {
	//創建請求者
	 RequestPerson person =new RequestPerson();
	 //創建具體命令並指定接收者
	 Command command1=new PrintEnglishCommand(new PrintLetter());
	 Command command2=new PrintRussianCommand(new PrintLetter());
	 Command command3= new PrintEvenNumber(new PrintNumber(20));
	 ArrayList<Command> list= new ArrayList<Command>();
	 list.add(command1);
	 list.add(command2);
	 list.add(command3);
	 //創建宏命令
	 Command macroCommand=new MacroCommand(list);
	 System.out.println("單獨輸出英文字母表:");
	 person.setCommand(command1);
	 person.startExcuteCommand();
	 System.out.println();
	 System.out.println("宏命令執行");
	 person.setCommand(macroCommand);
	 person.startExcuteCommand();
	 
}
}

運行效果截圖:

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章