设计模式 --- 命令模式

1.定义

将一个请求封装成一个对象,从而让用户使用不同的请求把客户端参数化;对请求排队或者记录请求日志,以及支持可撤销的操作。

2.使用场景

需要抽象出待执行的动作,然后以参数的形式提供出来,类似于过程设计中的回调机制。

在不同的时刻指定、排列和执行请求。

需要支持取消操作。

支持修改日志功能。

需要支持事物操作。

3.简单实现

以一个电视遥控器功能为例,遥控器能控制电视机的开机、关机、调解音量、切换频道。

//定义一个接收者角色,真正具体处理逻辑的方法
class TvFunction{
    //执行开机
    void PowerOn(){
        System.out.println("底层调用硬件通电...开机");
    }
    //执行关机
    void PowerOff(){
        System.out.println("底层调用硬件断电...关机");
    }
    //执行频道切换
    void ChangeChannal(){
        System.out.println("调用底层程序代码...切换频道");
    }
    //执行音量调节
    void TurnVoice(){
        System.out.println("调用底层程序代码...调节音量");
    }
}

interface Command{
    //命令执行的方法
    void execute();
}

//开机命令
class PowerOn implements Command{
    //持有一个接收者的引用
    private TvFunction function;

    public PowerOn(TvFunction function) {
        this.function = function;
    }

    @Override
    public void execute() {
        //调用具体的开机方法
        function.PowerOn();
    }
}

//关机命令
class PowerOFF implements Command{
    //持有一个接收者的引用
    private TvFunction function;

    public PowerOFF(TvFunction function) {
        this.function = function;
    }

    @Override
    public void execute() {
        //调用具体的关机机方法
        function.PowerOff();
    }
}

//频道切换命令
class Channal implements Command{
    //持有一个接收者的引用
    private TvFunction function;

    public Channal(TvFunction function) {
        this.function = function;
    }

    @Override
    public void execute() {
        //调用具体的切换频道方法
        function.ChangeChannal();
    }
}

//音量调节命令
class Voice implements Command{
    //持有一个接收者的引用
    private TvFunction function;

    public Voice(TvFunction function) {
        this.function = function;
    }

    @Override
    public void execute() {
        //调用具体的音量调节方法
        function.TurnVoice();
    }
}

//定义请求者 遥控器
class TvContorllor{
    private PowerOn powerOn; //开机对象的引用
    private PowerOFF powerOFF; //关机对象的引用
    private Channal channal;    //频道切换对象的引用
    private Voice voice;    //音量调节对象的引用

    public void setPowerOn(PowerOn powerOn) {
        this.powerOn = powerOn;
    }

    public void setPowerOFF(PowerOFF powerOFF) {
        this.powerOFF = powerOFF;
    }

    public void setChannal(Channal channal) {
        this.channal = channal;
    }

    public void setVoice(Voice voice) {
        this.voice = voice;
    }

    //开机
    public void powerOn(){
        powerOn.execute();
    }

    //关机
    public void powerOff(){
        powerOFF.execute();
    }

    //调解音量
    public void turnVoice(){
        voice.execute();
    }

    //切换频道
    public void changeChannal(){
        channal.execute();
    }
}

public class CommandMode {

    public static void main(String[] args){
        //首先要有电视机的功能
        TvFunction function = new TvFunction();

        //构造4种命令
        PowerOn powerOn = new PowerOn(function);
        PowerOFF powerOFF = new PowerOFF(function);
        Channal channal = new Channal(function);
        Voice voice = new Voice(function);

        //构造一个遥控器
        TvContorllor tvContorllor = new TvContorllor();
        tvContorllor.setPowerOn(powerOn);
        tvContorllor.setPowerOFF(powerOFF);
        tvContorllor.setChannal(channal);
        tvContorllor.setVoice(voice);

        //用户可以随便按遥控器控制电视
        tvContorllor.powerOn();
        tvContorllor.changeChannal();
        tvContorllor.turnVoice();
        tvContorllor.powerOff();
    }

输出:

调用逻辑做的如此复杂,原因是为了代码交给别人来维护时,比较清晰,遵循了设计模式重要原则:对修改关闭对拓展开放。此外,还有一个好处是可以再TvContorllor类中存储执行过的命令,我们可以方便知道执行过哪些命令,还可以恢复。

4.小结

优点:

更弱的耦合性,更灵活的控制性,更好的拓展性;

缺点:

类的膨胀,大量的衍生类

猜你喜欢

转载自blog.csdn.net/huxing0215/article/details/84299182