随笔分类
命令模式
Command
行为型之一
通过被称为Command的类封装了对目标对象的调用行为以及调用参数
在面向对象的程序设计中,一个对象调用另一个对象,一般情况下的调用过程是:创建目标对象实例;设置调用参数;调用目标对象的方法。
但在有些情况下有必要使用一个专门的类对这种调用过程加以封装,我们把这种专门的类称作command类。
- 整个调用过程比较繁杂,或者存在多处这种调用。这时,使用Command类对该调用加以封装,便于功能的再利用
- 调用的前后需要对参数进行某些处理
- 调用前后需要进行某些额外处理,比如日志,缓存,记录历史操作等
- 其实说白了就是不直接去调用命令的真正执行者,将其封装起来,便于扩展
- Invoker:表面上命令的执行者,实际上直接和客户打招呼,持有Command的第一个引用
- Command:抽象命令,持有最终命令接收者的一个引用(Receiver)
- ConcreteCommand:具体的命令,通过调研Receiver来执行真正的命令
- Receiver:也就是最终命令的接收者与执行者了
/**
* 最终命令的接收者
* 也是命令的最终执行者
*/
public class Sellor {
public void sellApple(){
System.out.println("卖苹果");
}
public void sellBanana(){
System.out.println("卖香蕉");
}
}
public abstract class Command {
private Sellor sellor;
public Sellor getSellor() {
return sellor;
}
public Command(Sellor sellor) {
this.sellor = sellor;
}
public abstract void sell();
}
public class AppleCommand extends Command{
public AppleCommand(Sellor sellor) {
super(sellor);
}
@Override
public void sell() {
this.getSellor().sellApple();
}
}
public class BananaCommand extends Command{
public BananaCommand(Sellor sellor) {
super(sellor);
}
@Override
public void sell() {
this.getSellor().sellBanana();
}
}
public class Invoker {
//还是需要持有一个Command引用的
private Command command;
public void setCommand(Command command) {
this.command = command;
}
public void sell(){
command.sell();
}
}
/**
* 卖苹果
*/
public class Client {
public static void main(String[] args) {
Command appleCommand = new AppleCommand(new Sellor());
BananaCommand bananaCommand = new BananaCommand(new Sellor());
Invoker invoker = new Invoker();
invoker.setCommand(appleCommand);
invoker.sell();
invoker.setCommand(bananaCommand);
invoker.sell();
}
}
应用场景
- 数据库中事务机制的底层实现
- 命令的撤销和恢复:增加相应的恢复和撤销命令的方法(比如说是数据库中的事务回滚)