`
897371388
  • 浏览: 530998 次
文章分类
社区版块
存档分类
最新评论

学习设计模式之禅——命令模式

 
阅读更多

命令模式是一个高内聚的模式,其定义为:Encapsulate a request as an object,thereby letting you parameterize clients with different requests,queue or long queues,and support undoable operation(将一个请求封装成一个对象,从而让你使用不同的请求把客户端参数化,对请求排队或者记录请求日志,可以提供命令的撤销和恢复功能。)

命令模式使用的场景:

只要你认为是命令的地方都可以使用命令模式,例如,在GUI开发中,一个按钮的点击是一个命令,可以采用命令模式;模拟dos命令的时候,当然也要采用命令模式;触发——反馈机制的处理等。

命令模式有三个角色

Receiver接收者角色,传递到这里应该被执行的。

Command命令角色,需要执行的所有命令都在这里声明。

Invoker调用者角色,接收命令,并执行命令。


命名模式比较简单,但是在项目中非常频繁的使用,因为它的封装性非常好,把请求方(Invoker)和执行方(Receiver)分来了,扩展性也有很好的保障,通用代码比较简单,如下:

package com.freesonfish.freeson.command;

/**
 * @author freeson
 * 为什么该类是一个抽象类?那是因为接收者可以有多个,有多个就要定义一个所有特性的抽象集合——抽象的接收者
 */
public abstract class Receiver {

	//抽象接收者,定义每个接受者都必须完成的业务
	public abstract void doSomething();
}

接收者是N个,这要依赖业务的具体定义

package com.freesonfish.freeson.command;

public class ConcreteReceiver1 extends Receiver {

	//每个接收者都必须处理一定的业务逻辑
	@Override
	public void doSomething() {
	}

}
package com.freesonfish.freeson.command;

public class ConcreteReceiver2 extends Receiver {

	//每个接收者都必须处理一定的业务逻辑
	@Override
	public void doSomething() {
	}

}
命令角色是命令模式的核心,其抽象类如下:

package com.freesonfish.freeson.command;

public abstract class Command {

	//每个命令类都必须由一个执行命令的方法
	public abstract void execute();
}
根据环境的需求,具体的命令类也可以有N个。

public class ConcreteCommand1 extends Command {

	//对哪个Receiver类进行命令处理
	private Receiver receiver = null;
	
	public ConcreteCommand1(Receiver receiver) {
		this.receiver = receiver;
	}

	//必须实现一个命令
	@Override
	public void execute() {
		this.receiver.doSomething();
	}
}
package com.freesonfish.freeson.command;

public class ConcreteCommand2 extends Command {

	// 对哪个Receiver类进行命令处理
	private Receiver receiver = null;

	public ConcreteCommand2(Receiver receiver) {
		this.receiver = receiver;
	}

	// 必须实现一个命令
	@Override
	public void execute() {
		this.receiver.doSomething();
	}
}
定义调用者

package com.freesonfish.freeson.command;

/**
 * 
 * @author freeson
 * 
 * 调用者非常简单,仅实现命令的传递,不管什么命令,都要接收和执行
 *
 */
public class Invoker {

	private Command command = null;

	// 受气包,接受命令
	public void setCommand(Command command) {
		this.command = command;
	}

	// 执行命令
	public void action() {
		this.command.execute();
	}
}


场景类

package com.freesonfish.freeson.command;

public class Client {

	public static void main(String[] args) {
		//首先声明调用者Invoker
		Invoker invoker = new Invoker();
		//定义接收者
		Receiver receiver = new ConcreteReceiver1();
		//定义一个发送给接收者的命令
		Command command = new ConcreteCommand1(receiver);
		//把命令交给调用者去执行
		invoker.setCommand(command);
		invoker.action();
	}
}

命令模式的优点:

1)类间解耦,调用者角色与接收者角色之间没有任何依赖关系,调用者实现功能时只须调用Command抽象类的execute方法就可以了,不需要了解到底是那个接收者执行。

2)可扩展性,Command的之类可以非常容易地扩展,而调用者Invoker和高层次的模块Client不产生严重的代码耦合。

3)命令模式结合其他模式更加优秀,命令模式可以结合责任链模式,实现命令族解析任务;结合模板模式,则可以减少Command子类的膨胀问题。

命令模式的缺点:

命令模式也是有缺点的,请看Command的子类,如果有N个命令,问题就出来了,Command的子类就可不是几个,而是N个,这个类膨胀得非常大,这个就需要读者在项目慎重考虑了。




分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics