设计模式:命令模式 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();
	 
}
}

运行效果截图:

发布了91 篇原创文章 · 获赞 37 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/weixin_37716512/article/details/104378088