提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档


一、问题描述

  房间中的开关就是命令模式的一个实现,试用命令模式来模拟开关的功能,可控制对象包括电灯和电风扇,绘制相应的类图并使用对应的语言编程模拟。

二、问题分析

1.分析思路

  本题之所以把lighton和lightoff分开,这样虽然多增加了类,但是符合了开闭原则,因为若将on方法和off方法放在一个具体命令类里面,那么这样抽象命令类里面的接口就会改变,这样如果新加一个功能则会修改很多,非常麻烦。而如果设计成如下图所示的类图,新加一个功能则只需要再加几个类即可。

2.类图

在这里插入图片描述

三、命令模式简介

  命令模式(Command Pattern):将一个请求封装为一个对象,从而你可以用不同的请求对客户进行参数化,对请求排队或者记录请求日志,以及支持可撤销操作。上述类图符合了开闭原则、里氏代换原则、依赖倒转原则等等。

1.命令模式的优点

(1)降低了系统耦合度。
(2)命令模式的封装性很好:每个命令都被封装起来,对于客户端来说,需要什么功能就去调用相应的命令,而无需知道命令具体是怎么执行的。比如有一组文件操作的命令:新建文件、复制文件、删除文件。如果把这三个操作都封装成一个命令类,客户端只需要知道有这三个命令类即可,至于命令类中封装好的逻辑,客户端则无需知道。
(3)命令模式的扩展性很好,在命令模式中,在接收者类中一般会对操作进行最基本的封装,命令类则通过对这些基本的操作进行二次封装,当增加新命令的时候,对命令类的编写一般不是从零开始的,有大量的接收者类可供调用,也有大量的命令类可供调用,代码的复用性很好。比如,文件的操作中,我们需要增加一个剪切文件的命令,则只需要把复制文件和删除文件这两个命令组合一下就行了,非常方便。
(4)可以实现宏命令。命令模式可以与组合模式结合,将多个命令装配成一个组合命令,即宏命令。
(5)方便实现 Undo 和 Redo 操作。命令模式可以与后面介绍的备忘录模式结合,实现命令的撤销与恢复。
(6)增加或删除命令非常方便。采用命令模式增加与删除命令不会影响其他类,它满足“开闭原则”,对扩展比较灵活。

2.命令模式的缺点

(1)使用命令模式可能会导致某些系统有过多的具体命令类。因为针对每一个命令都需要设计一个具体命令类,因此某些系统可能需要大量具体命令类,这将影响命令模式的使用。

3.应用场景

(1)struts1中的action核心控制器ActionServlet只有一个,相当于Invoker,而模型层的类会随着不同的应用有不同的模型类,相当于具体的Command。
(2)系统需要将请求调用者和请求接收者解耦,使得调用者和接收者不直接交互。
(3)系统需要在不同的时间指定请求、将请求排队和执行请求。
(4)系统需要支持命令的撤销(Undo)操作和恢复(Redo)操作。
(5)系统需要将一组操作组合在一起,即支持宏命令。

四、代码及结果

项目目录:
在这里插入图片描述
Command接口类:

public interface Command {
  void excute();
}

具体命令类——LightOffCommand:

public class LightOffCommand implements Command{
  private Light light;
   LightOffCommand(Light light)
   {
        this.light = light;
   }
    @Override
    public void excute() {
        light.off();
    }
}

具体命令类——ElectricFanOnCommand:(其他具体命令类类似)

public class ElectricFanOnCommand implements Command{
   private ElectricFan electricFan;
    ElectricFanOnCommand(ElectricFan electricFan)
   {
       this.electricFan = electricFan;
  }
    @Override
    public void excute() {
        electricFan.on();
   }
 }

接收者类——Light(ElectriFan类似):

public class Light {
    private boolean on = false  ;
    public void on()
    {
        System.out.println("开灯");
        on = true;
   }
    public void off()
    {
        System.out.println("关灯");
        on = false ;
    }
    public boolean Ison()
    {
       return on;
    }
}

发送者类——RemoteController:

public class RemoteController {
    Command[] oncommand;
    Command[] offcommand;
    RemoteController(int commandsize)
    {
        oncommand = new Command[commandsize];
        offcommand = new Command[commandsize];
    }
    public void setCommand(int i, Command onCommand, Command offCommand) {
        oncommand[i] = onCommand;
        offcommand[i] = offCommand;
    }
   public void onButtonPressed(int i)
    {
        oncommand[i].excute();
    }
    public void offButtonPressed(int i)
   {
        offcommand[i].excute();
    }
}

Client类:

public class Clint {
    public static void main(String[]args) {
        Light light = new Light();
        ElectricFan electricFan = new ElectricFan();
        Command electricFanOnCommand = new ElectricFanOnCommand(electricFan);
        Command electricFanOffCommand = new ElectricFanOffCommand(electricFan);
        Command lightOnCommand = new LightOnCommand(light);
        Command lightOffCommand = new LightOffCommand(light);
        RemoteController remoteController = new RemoteController(2);
        remoteController.setCommand(0,electricFanOnCommand,electricFanOffCommand);
        remoteController.setCommand(1,lightOnCommand,lightOffCommand);
        remoteController.offButtonPressed(1);
       remoteController.offButtonPressed(0);
        remoteController.onButtonPressed(0);
        remoteController.onButtonPressed(1);
    }
}

运行结果:
在这里插入图片描述

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐