命令模式

目录

 

0. 背景概述

1. 命令模式介绍

1.1 命令模式定义

1.2 命令模式UML结构图

2. 命令模式的Java实现

2.1 UML结构图

2.2 Java用例代码 

3.宏命令

3.1 宏命令UML结构图

3.2 java宏命令用例代码

 4.命令模式的特点

5.结语


0. 背景概述

用例1:现在我们使用的电视机已经相当的高端了,超薄,连接互联网,但是在上世纪80,90年代的时候电视机不仅笨重,而且接收的电视信号也好,只有一个按钮用来调频,如果我们想换个电视台怎么办?只能跑到电视机前面转动调频按钮,每次转换都需要人与电视机来交互,但是现在的电视机有了遥控器,可以直接遥控电视,将人与电视机的交互分割开来,这是一项很重要的技术变革。

用例2:历史上秦始皇嬴政利用十年的时间统一六国,建立秦朝,这期间,作为君王,他殚精竭虑,大家想,统一六国管理一个国家需要做多少事情?如果都由嬴政一个人来干岂不是要累死了,怎么办?下指令交给下面的大臣来办,比如丞相李斯协助嬴政处理军政大事。嬴政就能够专注与国家大事,从繁琐的事务中抽离开来。

我们来分析以上两个用例,遥控的出现分离了人与电视机的交互,作为具体命令的请求者使得人与命令的接收者(电视机)解耦,李斯的存在,将嬴政与具体的军国大事的执行分离,嬴政颁布圣旨给李斯,李斯下达命令(命令请求者),指派给具体需要工作的人(命令接收者)。而在软件设计中,行为的请求者与行为的处理者大部分都是一种紧耦合的关系,不利于系统的扩展,也不符合设计模式的原则,命令模式将两者解耦,每个命令即一个操作,请求者发出命令要求执行一个操作,接收者接收命令执行这个操作,两者各司其职。

1. 命令模式介绍

1.1 命令模式定义

命令模式:(Command Pattern),将一个请求封装为一个对象,从而使我们可用不同的请求对客户进行参数化;对请求排队或者记录请求日志,以及支持可撤销的操作。(定义取自   Java与模式一书)

1.2 命令模式UML结构图

Client:客户端角色,操作者的主要请求者

Invoker:执行者角色,接收客户端(Client)下达的具体指令,持有一个命令对象,调用命令对象来执行具体的命令操作。

Command:抽象命令接口,声明了所有具体的命令的公共行为。

ConcreteCommand:具体命令实现类,实现了抽象命令接口,关联了一个具体的命令接收者角色。

Receiver:具体的命令接收者,收到命令后执行此命令。

用例1中,就是Client遥控器就是Invoker,遥控器上面的所有按键抽象为Command,具体的比如音量+,音量-等按键就是具体的ConcreteCommand,而电视机就是Receiver

用例2中,嬴政就是Client,丞相李斯就是Invoker,圣旨Command,具体每道圣旨为具体的ConcreteCommand,而圣旨上面的执行人就是Receiver

 

2. 命令模式的Java实现

本节将以用例2为例,使用Java实现命令模式,JDK版本为Java10。

2.1 UML结构图

Emperor:始皇嬴政

PrimeMinister:丞相李斯,传达始皇帝的命令。

Decree:抽象圣旨。

ConcreteDecreeFood:具体发布筹集粮草的圣旨。

ConcreteDecreeBattle:具体攻打赵国的圣旨。

Receiver:圣旨的接收者(这里为抽象类)。

DaSiNong:大司农,筹集粮草。

WangJian:大将军,攻打赵国。

2.2 Java用例代码 

Decree抽象接口

public interface Decree {

    void execute();
}

ConcreteDecreeFood实现

public class ConcreteDecreeFood implements Decree{

    private Receiver receiver;

    public  ConcreteDecreeFood(Receiver receiver){
        this.receiver=receiver;
    }
    @Override
    public void execute() {
        System.out.println("统一六国,命令"+this.receiver.getName()+"准备充足的粮草");
        this.receiver.execute();
    }
}

ConcreteDecreeBattle实现

public class ConcreteDecreeBattle implements Decree {

    private Receiver receiver;

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

    @Override
    public void execute() {
        System.out.println("攻打赵国,命令" + this.receiver.getName() + "为将,出征");
        this.receiver.execute();
    }
}

Receiver抽象类实现

public abstract class Receiver {

    /**
     * 圣旨接收人的名字
     */
    private String name;
    public Receiver(String name){
        this.name=name;
    }

    /**
     * 抽象执行方法
     */
    public abstract void execute();

    public String getName() {
        return name;
    }
}

WangJian具体接收者实现

public class WangJian extends Receiver {


    public WangJian(String name) {
        super(name);
    }

    @Override
    public void execute() {
        System.out.println("微臣" + this.getName() + "领命");
    }
}

DaSiNong具体接收者实现

public class DaSiNong extends Receiver {
    public DaSiNong(String name) {
        super(name);
    }

    @Override
    public void execute() {
        System.out.println("臣"+this.getName()+"领命,必当征集足够粮草");
    }
}

PrimeMinister实现

public class PrimeMinister {
    /**
     * 关联抽象圣旨对象
     */
    private Decree decree;

    /**
     * 颁布具体圣旨
     */
    public void publish(){
        System.out.println("颁布圣旨");
        this.decree.execute();
    }

    public Decree getDecree() {
        return decree;
    }

    public void setDecree(Decree decree) {
        this.decree = decree;
    }
}

Emperor实现

public class Emperor {
    public static void main(String[] args) {
        //命令接收者大司农角色(忘记叫啥了,用XXX代替吧)
        Receiver receiver=new DaSiNong("XXX");

        //创建筹集粮草的圣旨
        Decree decree=new ConcreteDecreeFood(receiver);

        //圣旨交给李斯
        PrimeMinister primeMinister=new PrimeMinister();
        primeMinister.setDecree(decree);
        primeMinister.publish();

        //命令接收者大将军角色(忘记叫啥了,用XXX代替吧)
        receiver=new WangJian("王翦");

        //创建征战的圣旨
        decree=new ConcreteDecreeBattle(receiver);

        //交给李斯执行
        primeMinister.setDecree(decree);
        primeMinister.publish();
    }
}

运行结果如下:

3.宏命令

经过10年征战,嬴政终于灭掉六国,建立大一统的秦朝,为了巩固自己的政权,秦始皇连续颁布了一系列圣旨,主要包括废分封,立郡县,统一文字和度量衡,修筑长城,此时对于这一系列的制度颁布,可以增加宏命令功能来实现。

宏命令是命令模式与组合模式的一起使用的产物,主要增加了一个组合命令接口,批量执行一系列的命令。

3.1 宏命令UML结构图

CompositDecree:圣旨组合接口,实现了Decree接口,由addDecree()与removeDecree()方法。

CompositDecreeImpl:组合接口的具体实现类。 

EveryPeople:Receiver的实现类,秦朝子民。

3.2 java宏命令用例代码

EveryPeople代码

public class EveryPeople extends Receiver {
    public EveryPeople(String name) {
        super(name);
    }

    @Override
    public void execute() {
        System.out.println("好的,遵命");
    }
}

CompositDecree代码

public interface CompositDecree extends Decree {
    /**
     * 增加一道圣旨
     * @param decree
     */
    void addDecree(Decree decree);

    /**
     * 删除一道圣旨
     * @param decree
     */
    void removeDecree(Decree decree);


}

CompositDecreeImpl代码

public class CompositDecreeImpl implements CompositDecree {

    private List<Decree> decreeList = new ArrayList<>();

    @Override
    public void execute() {
        decreeList.forEach(Decree::execute);
    }

    @Override
    public void addDecree(Decree decree) {
        decreeList.add(decree);
    }

    @Override
    public void removeDecree(Decree decree) {
        decreeList.remove(decree);
    }
}

ConcreteDecreeA代码

public class ConcreteDecreeA implements Decree {
    private Receiver receiver;

    public ConcreteDecreeA(Receiver receiver) {
        this.receiver = receiver;
    }
    @Override
    public void execute() {
        System.out.println(this.receiver.getName()+",我们废除分封制度,设计郡县制度");
        this.receiver.execute();
    }
}

ConcreteDecreeB代码

public class ConcreteDecreeB implements Decree {
    private Receiver receiver;

    public ConcreteDecreeB(Receiver receiver) {
        this.receiver = receiver;
    }
    @Override
    public void execute() {
        System.out.println(this.receiver.getName()+",我们要统一文字,度量衡");
        this.receiver.execute();
    }
}

ConcreteDecreeC代码

public class ConcreteDecreeC implements Decree {
    private Receiver receiver;

    public ConcreteDecreeC(Receiver receiver) {
        this.receiver = receiver;
    }
    @Override
    public void execute() {
        System.out.println(this.receiver.getName()+",为了抵御匈奴,来吧,咱们修长城");
        this.receiver.execute();
    }
}

Emperor代码

public class Emperor {
    public static void main(String[] args) {
        //命令接收者秦朝子民角色
        Receiver receiver=new EveryPeople("秦朝子民");

        //创建宏命令
        Decree compositDecree=new CompositDecreeImpl();
        //创建废除分封制度圣旨
        Decree decree=new ConcreteDecreeA(receiver);
        ((CompositDecreeImpl) compositDecree).addDecree(decree);


        //创建统一文字制度圣旨
         decree=new ConcreteDecreeB(receiver);
        ((CompositDecreeImpl) compositDecree).addDecree(decree);

        //创建修筑长城圣旨
         decree=new ConcreteDecreeC(receiver);
        ((CompositDecreeImpl) compositDecree).addDecree(decree);
        //圣旨交给李斯
        PrimeMinister primeMinister=new PrimeMinister();
        primeMinister.setDecree(compositDecree);
        primeMinister.publish();
    }
}

运行结果如下:

 4.命令模式的特点

优点:命令模式将请求的发出者与请求的接收者进行了解耦,新增加一个命令只需要扩展即可,体现了设计模式原则的开闭原则,系统能够保持很好的扩展性。而且命令模式与组合模式的联合可以批量的执行命令。

缺点:系统中,如果命令过多可能造成大量命令类的存在,使系统功能过于臃肿。

5.结语

本篇文章讲解了命令模式的基本结构以及用例,在具体的系统设计中,应该根据实际情况来设计,避免设计模式的滥用而导致系统更加的复杂

 

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值