`

命令模式--(1)基本认识

阅读更多

什么是命令模式:

 

 

将请求(命令)封装为对象,实现将“发出请求的对象”与“接收和执行这些请求的对象”分隔开来

 

命令模式中有几个关键的概念:

 

客户:发起请求的对象,开关,或者你(因为开关是由你来控制的)

命令:具体的一个命令,比如开灯命令,关灯命令

执行者:接收和执行请求的对象,比如电灯,是开灯关灯命令的接收者和执行者

调用者:通过这个对象来实现客户(开关或你)和执行者(电灯)之间的耦合

 

命令模式支持撤销。对于这个demo来说,开灯这个命令对应的撤销就是关灯。同理:关灯命令对应的撤销就是开灯。

LightOnCommand.java文件可以看到这一点,我通过一个List维护着用户的开灯和关灯的命令,当用户需要撤销的时候,从取出这个List的最后一个Command,执行它的undo()就实现了撤销。当然实现后你还要记得remove它,才能实现撤销到更早的Command。

这里我用一个ImageView当做灯泡。通过切换不同的图片,来实现on和off.

 

 

假如现在我要使用命令模式做一个类似按钮打开和关闭电灯的引用。实现效果如下图:

 

 

下面是工程结构:

 

 

 

 

我将开灯和关灯这两个命令封装成对象,它们都实现了Command接口,RemoteInvoker就是调用者。

下面上代码:

 

Command.java:

 

 

/**
 * 这是第一步,让所有的命令对象实现相同的包含一个方法的接口
 * 
 * */
public interface Command {

	public void execute();
	public void undo();
}
 

 

实现这个接口:

LightOnCommand.java:(LightOffCommand.java是类似的,只不过图片是相反的,这里就不贴代码了)

 

 

public class LightOnCommand implements Command{

	private ImageView light;
	
	public LightOnCommand(ImageView light){
		
		this.light = light;
	}
	
	@Override
	public void execute() {
		
		light.setBackgroundResource(R.drawable.light_on);
	}
	
	@Override
	public void undo() {
		
		light.setBackgroundResource(R.drawable.light_off);
	}
	
	@Override
	public String toString() {

		return "On Command";
	}
	
}
 

 

RemoteInvoker.java:

 

 

/**
 * 这个就是遥控器类,这个类在这里还负责撤销操作
 * 
 * */
public class RemoteInvoker {

	Command slot;
	Command onCommand;
	Command offCommand;
	LinkedList<Command> commandList;
	Context context;
	
	public RemoteInvoker(Context context) {
		
		this.context = context;
		commandList = new LinkedList<Command>();
	}
	
	public void setCommand(Command onCommand, Command offCommand){
		
		this.onCommand = onCommand;
		this.offCommand = offCommand;
	}
	
	public void onButtonWasPressed(){
		
		onCommand.execute();
		commandList.add(onCommand);
	}
	
	public void offButtonWasPressed(){
		
		offCommand.execute();
		commandList.add(offCommand);
	}
	
	public void undoButtonWasPressed(){
		
		for(Command c: commandList){
			Log.e("**********:", ":"+c.toString());
		}
		
		int sizeOfCommands = commandList.size();
		if(sizeOfCommands <= 0){
			
			Toast.makeText(context, "当前已经没有要撤销的对象了", Toast.LENGTH_SHORT).show();
		}else{
			
			Command lastCommand = commandList.get(sizeOfCommands - 1);//获取最后一个命令对象,执行它的undo方法
			lastCommand.undo();
			commandList.removeLast();//删除最后一个命令
		}
		
		
	}
}
 

 

最后是调用者类

MainActivity.java:

 

 

public class MainActivity extends Activity {

	private RemoteInvoker remoteInvoker;
	private LightOnCommand lightOnCommand;
	private LightOffCommand lightOffCommand;
	private ImageView light;
	
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        
        light = (ImageView)findViewById(R.id.iv_light);//灯泡
        Button btnOn = (Button)findViewById(R.id.btn_light_on);//开
        Button btnOff = (Button)findViewById(R.id.btn_light_off);//关
        Button btnUndo = (Button)findViewById(R.id.btn_undo);//撤销
        
        //步骤1
        lightOnCommand = new LightOnCommand(light);//实例化命令
        lightOffCommand = new LightOffCommand(light);
        
        //步骤2
        remoteInvoker = new RemoteInvoker(this);
        remoteInvoker.setCommand(lightOnCommand, lightOffCommand);//设置命令
        
        btnOn.setOnClickListener(clickListener);
        btnOff.setOnClickListener(clickListener);
        btnUndo.setOnClickListener(clickListener);
    }

    private View.OnClickListener clickListener = new View.OnClickListener() {
		
		@Override
		public void onClick(View v) {
			switch (v.getId()) {
			case R.id.btn_light_on://开灯
				remoteInvoker.onButtonWasPressed();
				break;
			case R.id.btn_light_off://关灯
				remoteInvoker.offButtonWasPressed();
				break;
			case R.id.btn_undo://撤销
				remoteInvoker.undoButtonWasPressed();
				break;
			default:
				break;
			}
		}
	};
    
}
 

 

 

 

这样做之后,你就当你要开灯或关灯的时候,就不需要直接对电灯的实例进行操作了,而是通过RemoteInvoker对象,你只要告诉这个对象,你按下了哪个按钮,其它的事情交个这个对象去处理。那么你和电灯之间就解耦了。

还有一点好处是,你可以实现命令的撤销。

 

当然,命令模式还支持批量执行命令,以及批量撤销命令。比如我只要按下一个按钮,那么多个命令(打开电灯,打开空调,打开电视就都开始执行),当我按关闭按钮,那么就撤销前面所有的命令。

 

还有队列请求日志请求的功能,这些等到下次再结合实例讲解演示。

 

 

 

 

 

 

 

 

  • 大小: 225.5 KB
  • 大小: 34.3 KB
0
1
分享到:
评论
2 楼 michaelye1988 2012-11-09  
sakajiaofu 写道
主要实现了调用者 和真正的动作实现者之间的解耦
也就是说中间会有一个过渡者 这个过渡者会和这两者进行交互


嗯,说的很好啊,这个过渡者就是RemoteInvoker。一对比,觉得自己语言能力还有待加强。谢谢指教。
1 楼 sakajiaofu 2012-11-09  
主要实现了调用者 和真正的动作实现者之间的解耦
也就是说中间会有一个过渡者 这个过渡者会和这两者进行交互

相关推荐

    Access2003中文版应用基础教程part1

    8-1-1 认识工具箱与控件 8-1-2 建立新的空白窗体 8-1-3 建立新的控件 8-2 控件的高级编辑技巧 8-2-1 复制控件 8-2-2 复制控件的格式 8-2-3 设置控件的Tab键顺序 8-3 控件的应用 8-3-1 自制数据操作按钮 8-3...

    Access2003中文版应用基础教程part2

    8-1-1 认识工具箱与控件 8-1-2 建立新的空白窗体 8-1-3 建立新的控件 8-2 控件的高级编辑技巧 8-2-1 复制控件 8-2-2 复制控件的格式 8-2-3 设置控件的Tab键顺序 8-3 控件的应用 8-3-1 自制数据操作按钮 8-3...

    《10天掌握MongoDB》2012完整版.pdf[带书签]

    MONGODB的基本数据类型 MONGODB的数组 MONGODB的文档嵌套 MONGODB的OBJECTID 结束语 第二天:初识增删改 添加文档 删除文档 更新文档-文档更换1 更新文档-文档替换2 更新文档-UPSERT模式 更新文档-MULTI模式 更新...

    例说51单片机C语言第三版练习程序

    2-1-1 认识mvision3环境 34 2-1-2 项目管理与选项 37 2-1-3 认识调试/仿真环境 39 2-1-4 外围操作 40 2-2 keil c语言的基本结构 43 2-3 变量、常数与数据类型 47 2-3-1 数据类型 47 2-3-2 变量名称与...

    入门学习Linux常用必会60个命令实例详解doc/txt

    如果选择用命令行模式登录Linux的话,那么看到的第一个Linux命令就是login:。 一般界面是这样的: Manddrake Linux release 9.1(Bamboo) for i586 renrel 2.4.21-0.13mdk on i686 / tty1 localhost login:root ...

    虚拟局域网的基本配置-案例.docx

    一、认识 VLAN VLAN 是一种基于端口的虚拟局域网技术,允许在同一个物理网络中创建多个逻辑网络,每个逻辑网络都是一个独立的广播域。 VLAN 可以帮助网络管理员更好地管理和维护网络,提高网络的安全性和灵活性。 ...

    网络原理实验报告(交换机的基本配置与管理)

    认识Packet Tracer软件 Packet Tracher介绍 Packet Tracer是Cisco公司针对CCNA认证开发的一个用来设计、配置和故障排除网络的模拟软件。 Packer Tracer模拟器软件比Boson功能强大,比Dynamips操作简单,非常...

    网络安全技术与实施-项目3--交换机安全管理与配置.pptx

    交换机的常见配置模式 (1)用户模式 当用户通过交换机的控制台端口或Telnet会话连接并登录到交换机时,此时所处的命令执行模式就是用户EXEC模式。在该模式下,只执行有限的一组命令,这些命令通常用于查看显示系统...

    研磨设计模式之命令模式

    命令模式(Command)1 场景问题 1.1 如何开机计有些朋友看到这个标题会非常奇怪,电脑装配好了,如何开机?不就是按下启动按钮就可以了吗?难道还有什么玄机不成。对于使用电脑的客户——就是我们来说,开机确实很...

    计算机网络与通信--20120628--4稿技能部分(活页

    任务1 基本命令 22 任务2 配置不带认证的PPP协议 22 任务3 配置带PAP认证的PPP协议 23 任务4 配置带CHAP认证的PPP协议 24 实训八:无线网络连接 25 任务1:使用AP组建无线局域网 25 任务2 使用无线路由器连入互联网 ...

    史上最强的嵌入式底层驱动开发课程 Linux系统开发+Linux高级程序+主板开发+ARM等

    │ ├01 - 从零开始认识开发板1.mp4 │ ├02 - 从零开始认识开发板2.mp4 │ ├03 - 从零开始认识开发板3.mp4 │ ├04 - 从零开始认识开发板4.mp4 │ └05 - 从零开始认识开发板5.mp4 ├&lt;1 Linux操作系统基础&gt; │ ├...

    大学计算机网络实验1-7

    实验一:1.了解双绞线;...实验六:掌握 RIP 路由协议的应用与配置,通过 RIP 协议相关命令实现动态路由,认识 RIP 的负载均衡 实验七:1、掌握单臂路由配置方法。 2、通过单臂路由实现不同 VLAN 间的通信

    路由器及其配置方法实验报告

    一 实验目的 1.认识路由器产品; 2.了解路由器的不同工作模式及其相应的配置命令; 3.掌握路由器不同模式之间的转换方法; 4.了解路由器的基本...4.路由器基本命令的使用(模式转换命令、特权模式下的配置命令等)。

    Head.First设计模式_PDF.part1

    6 命令模式:封装调用 7 适配器模式与外观模式:随遇而安 8 模板方法模式:封装算法 9 送代器与组合模式:管理良好的集合 10 状态模式:事物的状态 11 代理模式:控制对象访问 12 复合模式:模式中的...

    C#23种设计模式_示例源代码及PDF

    命令模式把发出命令的责任 命令模式 和执行命令的责任分割开,委派给不同的对象。命令模式允许请求的一方和发送的一方 独 立开来,使得请求的一方不必知道接收请求的一方的接口,更不必知道请求是怎么被接收, 以及...

    交换机及其配置方法实验报告

    一、实验目的: 1、认识交换机产品; 2、了解交换机的不同工作模式及其相应的配置命令; 3、掌握交换机不同模式之间的转换方法;...4、交换机基本命令的使用(模式转换命令、特权模式下的配置命令等)。

    Editplus 3[1].0

    这个也算正则表达式的用法,其实仔细看正则表达式应该比较简单,不过既然有这个问题提出,说明对正则表达式还得有个认识过程,解决方法如下 解决: 在替换对话框中,启用“正则表达式”复选框 在查找内容里面输入...

    什么是VLAN

    通过认识VLAN的本质,将可以了解到其用处究竟在哪些地方。  第一,要知道192.168.1.2/30和192.168.2.6/30都属于不同的网段,都必须要通过路由器才能进行访问,凡是不同网段间要互相访问,都必须通过路由器。  第二...

Global site tag (gtag.js) - Google Analytics