设计模式学习与整理-命令模式

应用场景

        在软件系统中,行为请求者与行为实现者通常是一种紧耦合的关系,但某些场合,比如需要对行为进行记录、撤销或重做、事务等处理时,这种无法抵御变化的紧耦合的设计就不太合适。

模式结构:

            Command:定义命令的统一接口

            ConcreteCommand:Command接口的实现者,用来执行具体的命令,某些情况下可以直接用来充当Receiver。

            Receiver:命令的实际执行者

            Invoker:命令的请求者,是命令模式中最重要的角色。这个角色用来对各个命令进行控制。

代码案例一:

    话说春秋战国时代,大将军想派某军队夜袭某城,却又不能自己去通知,于是将命令下达了下去。

    首先,创建请求者类(大将军)。

    

public class ArmySuperior {

    Command command;//创建命令的引用

    //用来存放具体命令的引用
    public void setCommand(Command command){
        this.command = command;
    }

    //让具体命令执行execute()方法,偷袭敌人
    public void startExecuteCommand(){
        command.execute();
    }

}

    接着,创建创建接受者,也叫执行者(某军队)。    

public class CompanyArmy {

    //接受者执行如何偷袭敌人
    public void sneakAttack(){
        System.out.println("我们知道如何偷袭敌人,保证完成任务!!!");
    }

}

    重点:请求者与接收者完全松耦合,这是命令模式的特点。

    创建命令接口。

public interface Command {

    public abstract void execute();

}

    创建命令接口的实现类。    

public class ConcreteCommand implements Command {

    CompanyArmy army;   //创建接受者引用

    ConcreteCommand(CompanyArmy army){
        this.army = army;
    }

    //封装指挥官的请求
    @Override
    public void execute(){
        army.sneakAttack();       //偷袭敌人
    }

}

最后,main方法所在的类。

public class OneApplication {

    public static void main(String[] args) {
        //接收者
        CompanyArmy companyArmy = new CompanyArmy();
        //命令实现类,将接收者传入
        ConcreteCommand concreteCommand = new ConcreteCommand(companyArmy);
        ArmySuperior superior = new ArmySuperior();
        superior.setCommand(concreteCommand);
        superior.startExecuteCommand();
    }

}

执行结果:

代码案例二:

    某商人想让服务人员帮忙买卖股票,这时就有买和卖两个动作了,就需要两个命令实现类了。

    首先还是请求者与接受者类。

/*请求者类*/
public class Broker {

    private List<Order> orderList = new ArrayList<Order>();

    public void takeOrder(Order order){
        orderList.add(order);
    }

    public void placeOrders(){
        for (Order order : orderList) {
            order.execute();
        }
        orderList.clear();
    }
}
/**接收者*/
public class Stock {

    public void buy(){
        System.out.println("Stock bought");
    }
    public void sell(){
        System.out.println("Stock sold");
    }
}

接着,创建命令接口。

public interface Order {

    void execute();

}

创建两个操作的命令实现类。

public class BuyStock implements Order{

    private Stock abcStock;

    public BuyStock(Stock abcStock){
        this.abcStock = abcStock;
    }

    @Override
    public void execute() {
        abcStock.buy();
    }

}
public class SellStock implements Order{

    private Stock abcStock;

    public SellStock(Stock abcStock){
        this.abcStock = abcStock;
    }

    @Override
    public void execute() {
        abcStock.sell();
    }
}

最后,创建main方法所在的类。

public class OneApplication {

    public static void main(String[] args) {
        Stock stock = new Stock();

        Order buyOrder = new BuyStock(stock);
        Order sellOrder = new SellStock(stock);

        Broker broker = new Broker();
        broker.takeOrder(buyOrder);
        broker.takeOrder(sellOrder);

        broker.placeOrders();
    }

}

我们发现,两个命令就需要两个命令实现类,这是命令模式的缺点。

命令接口除了execute()执行方法外,还可以添加撤销方法,并在命令实现类实现撤销方法,可以实现执行-撤销操作。

我们总结一下优缺点:

    优点: 

降低系统的耦合度:将调用操作的对象知道如何实现该操作的对象解耦。
Command是头等的对象。它们可像其他的对象一样被操纵和扩展
增加新的命令很容易,因为这无需改变已有的类
可以方便地实现对请求的Undo撤销和Redo恢复
命令模式结合其他模式会更优秀:命令模式可以结合责任链模式,实现命令族解析任务;结合模板方法模式,则可以减少 Command子类的膨胀问题。

    缺点:

因为每个命令都需要具体命令类,所以使用命令模式可能会导致某些系统有过多的具体命令类。

命令模式的其他应用:
宏命令模式:命令模式 加 组合模式,我们可以将多个命令组合到一起来实现命令的批处理。
队列请求:将命令排成一个队列打包,一个个调用 execute 方法,如线程池的任务队列,线程不关心任务队列中是读 IO 还是计算,只取出命令后执行,接着进行下一个。

日志请求:某些应用需要我们将所有的动作记录在日志中,然后在系统死机等情况出现时,重新调用这些动作恢复到之前的状态。如数据库事务。

 

参考链接:http://www.runoob.com/design-pattern/command-pattern.html                

                http://www.cnblogs.com/liuzhen1995/p/5971708.html

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值