命令模式讲解

命令模式讲解大纲

  • 命令模式原理介绍
  • 命令模式适用情况分析
  • 命令模式具体代码实现

原理介绍:

在软件系统中,“行为请求者”与“行为实现者”通常呈现一种“紧耦合”。但在某些场合,比如要对行为进行“记录、撤销/重做、事务”等处、理,这种无法抵御变化的紧耦合是不合适的。在这种情况下,如何将“行为请求者”与“行为实现者”解耦?将一组行为抽象为对象,实现二者之间的松耦合。这就是命令模式(Command Pattern)。

适用情况分析:

命令模式把命令抽象成对象,根据传入的命令对象来执行命令,从而减少的对象之间的耦合,比如我们有一个遥控器,遥控器有两列按钮,可以控制灯的开和关,音响的开和关,音响声音的增加和减少,那么我们可以使用命令模式来设计,我们设计一个命令接口,包含两个方面,一个是执行命令,一个是返回上一步,通过这个命令接口,我们来定义各种各样的命令对象,比如,开灯命令,关灯命令,开音响命令,关音响命令等,我们可以看出使用命令模式使这个模拟变的很好扩展,控制器和命令的执行耦合度很低,可以很容易的扩展命令和控制器.

具体代码实现:

命令接口:实现此接口即可扩展一个命令对象

package moshi.gunanyi.com.命令模式;
/**
 * 命令方法抽象
 * 命令模式使命令变成对象来解耦
 * @author Administrator
 *
 */
public interface Command {
	//执行命令
	public void execute();
	//回退命令
	public void undo();
}

灯类:

package moshi.gunanyi.com.命令模式;

public class Light {
	private String name;
	public Light(String name) {
		this.name = name;
	}
	
	public void On() {
		System.out.println(name+" 被打开");
	}
	
	public void Off() {
		System.out.println(name+" 被关闭");
	}
}

灯的命令:

package moshi.gunanyi.com.命令模式;
//关灯
public class LightOffCommand implements Command {
	private Light light;
	public LightOffCommand(Light light) {
		this.light = light;
	}
	@Override
	public void execute() {
		// TODO Auto-generated method stub
		light.Off();
	}

	@Override
	public void undo() {
		// TODO Auto-generated method stub
		light.On();
	}

}

package moshi.gunanyi.com.命令模式;
/**
 * 灯的开关
 * @author Administrator
 *
 */
 //开灯
public class LightOnCommand implements Command{
	private Light light;
	public LightOnCommand(Light light) {
		this.light = light;
	}
	@Override
	public void execute() {
		// TODO Auto-generated method stub
		light.On();
	}

	@Override
	public void undo() {
		// TODO Auto-generated method stub
		light.Off();
	}

}

音响类:

package moshi.gunanyi.com.命令模式;
/**
 * 音响类
 * @author Administrator
 *
 */
public class Stereo {
	private String name;
	private int vol;
	private String cdName;
	public Stereo(String name) {
		this.name = name;
		this.vol = 5;
	}
	
	public void On() {
		System.out.println(name+ " 被打开");
	}
	public void Off() {
		System.out.println(name+" 被关闭");
	}

	public int getVol() {
		return vol;
	}

	public void setVol(int vol) {
		this.vol = vol;
	}
	
	public void setCd() {
		System.out.println("放入CD");
	}
	
}

音响的命令:

音响的打开:

package moshi.gunanyi.com.命令模式;
/**
 * 音响的开关
 * @author Administrator
 *
 */
public class StereoOnCommand implements Command {
	private Stereo stereo;
	public StereoOnCommand(Stereo stereo) {
		this.stereo = stereo;
	}
	@Override
	public void execute() {
		stereo.On();
		stereo.setCd();
	}

	@Override
	public void undo() {
		stereo.Off();
	}

}

音响的关闭:

package moshi.gunanyi.com.命令模式;
/**
 * 关闭音响
 * @author Administrator
 *
 */
public class StereoOffCommand implements Command {
	private Stereo stereo;
	public StereoOffCommand(Stereo stereo) {
		this.stereo = stereo;
	}
	@Override
	public void execute() {
		// TODO Auto-generated method stub
		stereo.Off();
	}

	@Override
	public void undo() {
		// TODO Auto-generated method stub
		stereo.On();
	}

}

音响声音增加:

package moshi.gunanyi.com.命令模式;
/**
 * 音响的声音增加减少
 * @author Administrator
 *
 */
public class StereoAddVolCommand implements Command {
	private Stereo stereo;
	public StereoAddVolCommand(Stereo stereo) {
		this.stereo = stereo;
	}
	@Override
	public void execute() {
		// TODO Auto-generated method stub
		int vol = stereo.getVol();
		if(vol<11) {
			stereo.setVol(++vol);
		}
		System.out.println("音量增加:"+vol);
	}

	@Override
	public void undo() {
		int vol = stereo.getVol();
		if(vol>0) {
			stereo.setVol(--vol);
		}
		System.out.println("音量减少:"+vol);
	}

}

音响声音减小:

package moshi.gunanyi.com.命令模式;

public class StereoDecVolCommand implements Command {
	private Stereo stereo;
	public StereoDecVolCommand(Stereo stereo) {
		this.stereo = stereo;
	}
	@Override
	public void execute() {
		// TODO Auto-generated method stub
		int vol = stereo.getVol();
		if(vol>0) {
			stereo.setVol(--vol);
		}
		System.out.println("音量减少:"+vol);
	}

	@Override
	public void undo() {
		// TODO Auto-generated method stub
		int vol = stereo.getVol();
		if(vol<11) {
			stereo.setVol(++vol);
		}
		System.out.println("音量增加:"+vol);
	}

}

空命令:用于给控制器初始化,不然执行命令的时候需要判断命令是否为空

package moshi.gunanyi.com.命令模式;

public class NoCommand implements Command {

	@Override
	public void execute() {
		// TODO Auto-generated method stub

	}

	@Override
	public void undo() {
		// TODO Auto-generated method stub

	}

}

控制器接口:

package moshi.gunanyi.com.命令模式;
/**
 * 控制器方法抽象
 * @author Administrator
 *
 */
public interface Control {
	//开
	public void onButton(int slot);
	//关
	public void offButton(int slot);
	//返回上一次操作
	public void undoButton();
}

控制器的实现:

package moshi.gunanyi.com.命令模式;

import java.util.Stack;

public class CommandModeControl implements Control{
	private Command[] onCommands;
	private Command[] offCommands;
	//存储命令用来调用返回上一次操作
	private Stack<Command> undoCommand = new Stack<Command>();
	public CommandModeControl() {
		//共十个按钮
		onCommands = new Command[5];
		offCommands = new Command[5];
		Command noCommand = new NoCommand();
		//初始化按钮对象
		for(int i=0,len = onCommands.length;i<len;i++) {
			onCommands[i] = noCommand;
			offCommands[i] = noCommand;
		}
	}
	//设置按钮的命令
	public void setCommand(int slot,Command onCommand,Command offCommand) {
		onCommands[slot] = onCommand;
		offCommands[slot] = offCommand;
	}
	@Override
	public void onButton(int slot) {
		onCommands[slot].execute();
		undoCommand.push(onCommands[slot]);
	}
	@Override
	public void offButton(int slot) {
		offCommands[slot].execute();
		undoCommand.push(offCommands[slot]);
	}
	@Override
	public void undoButton() {
		undoCommand.pop().undo();
	}
}

代码测试:

package moshi.gunanyi.com.命令模式;
/**
 * 测试
 * @author Administrator
 *
 */
public class Test {

	public static void main(String[] args) {
	  //创建两个灯,一个音响
		Light keLight = new Light("客厅灯");
		Light woLight = new Light("卧室灯");
		Stereo stereo = new Stereo("大音响");
		
		Command keLightOnCommand = new LightOnCommand(keLight);
		Command keLightOffCommand = new LightOffCommand(keLight);
		Command woLightOnCommand = new LightOnCommand(woLight);
		Command woLightOffCommand = new LightOffCommand(woLight);
		
		Command stereoOnCommand = new StereoOnCommand(stereo);
		Command stereOffCommand = new StereoOffCommand(stereo);
		Command stereAddVolCommand = new StereoAddVolCommand(stereo);
		Command stereDesVolCommand = new StereoDecVolCommand(stereo);
		
		CommandModeControl commandModeControl = new CommandModeControl();
		commandModeControl.setCommand(0, keLightOnCommand, keLightOffCommand);
		commandModeControl.setCommand(1, woLightOnCommand, woLightOffCommand);
		commandModeControl.setCommand(2, stereoOnCommand, stereOffCommand);
		commandModeControl.setCommand(4, stereAddVolCommand, stereDesVolCommand);
		
		commandModeControl.onButton(1);
		//commandModeControl.offButton(1);
		commandModeControl.undoButton();
		commandModeControl.onButton(2);
		commandModeControl.onButton(4);
		commandModeControl.offButton(4);
		commandModeControl.offButton(2);
	}

}

测试结果:
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/qq_37520037/article/details/82758185