Go和Java实现命令模式
下面通过一个烧烤的例子来说明命令模式的使用。
1、命令模式
命令模式是一种数据驱动的设计模式,它属于行为型模式。请求以命令的形式包裹在对象中,并传给调用对象。调
用对象寻找可以处理该命令的合适的对象,并把该命令传给相应的对象,该对象执行命令。
-
意图:将一个请求封装成一个对象,从而使您可以用不同的请求对客户进行参数化,对请求排队或记录请求日
志,以及支持可撤消的操作。
-
主要解决:在软件系统中,行为请求者与行为实现者通常是一种紧耦合的关系,但某些场合,比如需要对行为
进行记录、撤销或重做、事务等处理时,这种无法抵御变化的紧耦合的设计就不太合适。
-
何时使用:在某些场合,比如要对行为进行"记录、撤销/重做、事务"等处理,这种无法抵御变化的紧耦合是
不合适的。在这种情况下,如何将"行为请求者"与"行为实现者"解耦?将一组行为抽象为对象,可以实现二者
之间的松耦合。
-
如何解决:通过调用者调用接受者执行命令,顺序:调用者→命令→接受者。
-
关键代码:定义三个角色:1、received 真正的命令执行对象 2、Command 3、invoker 使用命令对象的入口
-
应用实例:struts 1 中的 action 核心控制器 ActionServlet 只有一个,相当于 Invoker,而模型层的类会随着
不同的应用有不同的模型类,相当于具体的 Command。
-
优点:1、降低了系统耦合度。 2、新的命令可以很容易添加到系统中去。
-
缺点:使用命令模式可能会导致某些系统有过多的具体命令类。
-
使用场景:认为是命令的地方都可以使用命令模式,比如: 1、GUI 中每一个按钮都是一条命令。 2、模拟
CMD。
-
注意事项:系统需要支持命令的撤销(Undo)操作和恢复(Redo)操作,也可以考虑使用命令模式。
-
适用性:
抽象出待执行的动作以参数化某对象。
在不同的时刻指定、排列和执行请求。
支持取消操作。
支持修改日志,这样当系统崩溃时,这样修改可以被重做一遍。
用构建在原语操作上的高层操作构造一个系统。
2、Go实现命令模式
package command// ========== 声明执行操作的接口 ==========
// ========== Command ==========
type Command interface {// 执行命令executeCommand()
}
package command// ========== 将一个接收者对象绑定于一个动作,调用接收者相应的操作,以实现Execute ==========
// ========== BakeChickWingCommand烤鸡翅命令 ==========
type BakeChickWingCommand struct {Barbecuer
}func (bakeChickWingCommand *BakeChickWingCommand) executeCommand() {bakeChickWingCommand.Barbecuer.bakeChickWing()
}
package command// ========== 将一个接收者对象绑定于一个动作,调用接收者相应的操作,以实现Execute ==========
// ========== BakeMuttonCommand烤羊肉串命令 ==========
type BakeMuttonCommand struct {Barbecuer
}func (bakeMuttonCommand *BakeMuttonCommand) executeCommand() {bakeMuttonCommand.Barbecuer.bakeMutton()
}
package commandimport "fmt"// 知道如何实现与执行一个请求相关的操作,任何类都可能作为一个接收者
// ========== Barbecuer烧烤串者 ==========
type Barbecuer struct{}// 考羊肉串
func (barbecuer *Barbecuer) bakeMutton() {fmt.Println("考羊肉串!")
}// 考鸡翅
func (barbecuer *Barbecuer) bakeChickWing() {fmt.Println("考鸡翅!")
}
package command// 要求该命令执行这个请求
// ========== 服务员Waiter ==========
type Waiter struct {Command
}func (waiter *Waiter) SetOrder(command Command) {waiter.Command = command
}// 通知执行
func (waiter *Waiter) Execute() {waiter.Command.executeCommand()
}
package mainimport . "proj/command"func main() {// 开店前的准备// 烧烤师傅barbecuer := Barbecuer{}// 烧烤菜单bakeMuttonCommand := BakeMuttonCommand{Barbecuer: barbecuer}bakeChickWingCommand := BakeChickWingCommand{Barbecuer: barbecuer}// 服务员waiter := Waiter{}// 开门营业// 根据用户需要通知厨房waiter.SetOrder(&bakeMuttonCommand)// 开始制作waiter.Execute()waiter.SetOrder(&bakeChickWingCommand)waiter.Execute()
}
# 程序输出
考羊肉串!
考鸡翅!
3、Java实现命令模式
package com.command;// ========== 声明执行操作的接口 ==========
// ========== Command ==========
public abstract class Command {protected Barbecuer receive;public Command(Barbecuer receive) {this.receive = receive;}// 执行命令public abstract void executeCommand();
}
package com.command;// ========== 将一个接收者对象绑定于一个动作,调用接收者相应的操作,以实现Execute ==========
// ========== BakeChickWingCommand烤鸡翅命令 ==========
public class BakeChickWingCommand extends Command {public BakeChickWingCommand(Barbecuer receive) {super(receive);}@Overridepublic void executeCommand() {this.receive.bakeChickWing();}
}
package com.command;// ========== 将一个接收者对象绑定于一个动作,调用接收者相应的操作,以实现Execute ==========
// ========== BakeMuttonCommand烤羊肉串命令 ==========
public class BakeMuttonCommand extends Command {public BakeMuttonCommand(Barbecuer receive) {super(receive);}@Overridepublic void executeCommand() {this.receive.bakeMutton();}
}
package com.command;// 知道如何实现与执行一个请求相关的操作,任何类都可能作为一个接收者
// ========== Barbecuer烧烤串者 ==========
public class Barbecuer {// 考羊肉串public void bakeMutton(){System.out.println("考羊肉串!");}// 考鸡翅public void bakeChickWing(){System.out.println("考鸡翅!");}
}
package com.command;// 要求该命令执行这个请求
// ========== 服务员Waiter ==========
public class Waiter {private Command command;public void setOrder(Command command) {this.command = command;}// 通知执行public void execute() {this.command.executeCommand();}
}
package com.command;public class Test {public static void main(String[] args) {// 开店前的准备// 烧烤师傅Barbecuer barbecuer = new Barbecuer();// 烧烤菜单Command bakeMuttonCommand = new BakeMuttonCommand(barbecuer);Command bakeChickWingCommand = new BakeChickWingCommand(barbecuer);// 服务员Waiter waiter = new Waiter();// 开门营业// 根据用户需要通知厨房waiter.setOrder(bakeMuttonCommand);// 开始制作waiter.execute();waiter.setOrder(bakeChickWingCommand);waiter.execute();}
}
# 程序输出
考羊肉串!
考鸡翅!