喜欢 以前的 在本文中,让我们讨论一个设计问题来理解命令模式。假设你正在建造一个家庭自动化系统。有一个可编程的遥控器,可以用来打开和关闭家中的各种物品,比如灯、立体声、空调等。它看起来像这样。
你可以用简单的if-else语句来实现
if (buttonPressed == button1) lights.on()
但我们需要记住,打开一些设备,如立体声,包括许多步骤,如设置cd,音量等。我们还可以重新分配一个按钮来做其他事情。通过使用简单的if-else,我们正在编码实现,而不是接口。此外,还存在紧密耦合。
因此,我们想要实现的是一种提供松散耦合的设计,远程控制不应该有关于特定设备的太多信息。命令模式帮助我们做到这一点。
定义: 这个 命令模式 将一个请求封装为一个对象,从而使我们能够用不同的请求、队列或日志请求参数化其他对象,并支持可撤销的操作。
这个定义一开始有点让人困惑,但让我们来逐步了解一下。与我们上面的问题类似,遥控器是客户端,立体声、灯光等是接收器。在命令模式中,有一个命令对象 封装一个请求 通过将特定接收器上的一组操作绑定在一起。它通过只公开一个方法execute()来实现,该方法会导致在接收器上调用某些操作。
参数化具有不同请求的其他对象 在我们的类比中,用来开灯的按钮以后可以用来打开立体声,或者打开车库门。
排队或记录请求,并支持可撤销的操作 意味着命令的执行操作可以存储状态,以便在命令本身中反转其效果。该命令可能会添加一个unExecute操作,该操作会反转前一次执行调用的效果。它还可以支持记录更改,以便在系统崩溃时重新应用更改。
下面是上述远程控制示例的Java实现:
// A simple Java program to demonstrate // implementation of Command Pattern using // a remote control example. // An interface for command interface Command { public void execute(); } // Light class and its corresponding command // classes class Light { public void on() { System.out.println( "Light is on" ); } public void off() { System.out.println( "Light is off" ); } } class LightOnCommand implements Command { Light light; // The constructor is passed the light it // is going to control. public LightOnCommand(Light light) { this .light = light; } public void execute() { light.on(); } } class LightOffCommand implements Command { Light light; public LightOffCommand(Light light) { this .light = light; } public void execute() { light.off(); } } // Stereo and its command classes class Stereo { public void on() { System.out.println( "Stereo is on" ); } public void off() { System.out.println( "Stereo is off" ); } public void setCD() { System.out.println( "Stereo is set " + "for CD input" ); } public void setDVD() { System.out.println( "Stereo is set" + " for DVD input" ); } public void setRadio() { System.out.println( "Stereo is set" + " for Radio" ); } public void setVolume( int volume) { // code to set the volume System.out.println( "Stereo volume set" + " to " + volume); } } class StereoOffCommand implements Command { Stereo stereo; public StereoOffCommand(Stereo stereo) { this .stereo = stereo; } public void execute() { stereo.off(); } } class StereoOnWithCDCommand implements Command { Stereo stereo; public StereoOnWithCDCommand(Stereo stereo) { this .stereo = stereo; } public void execute() { stereo.on(); stereo.setCD(); stereo.setVolume( 11 ); } } // A Simple remote control with one button class SimpleRemoteControl { Command slot; // only one button public SimpleRemoteControl() { } public void setCommand(Command command) { // set the command the remote will // execute slot = command; } public void buttonWasPressed() { slot.execute(); } } // Driver class class RemoteControlTest { public static void main(String[] args) { SimpleRemoteControl remote = new SimpleRemoteControl(); Light light = new Light(); Stereo stereo = new Stereo(); // we can change command dynamically remote.setCommand( new LightOnCommand(light)); remote.buttonWasPressed(); remote.setCommand( new StereoOnWithCDCommand(stereo)); remote.buttonWasPressed(); remote.setCommand( new StereoOffCommand(stereo)); remote.buttonWasPressed(); } } |
输出:
Light is on Stereo is on Stereo is set for CD input Stereo volume set to 11 Stereo is off
请注意,遥控器不知道如何打开立体声。该信息包含在单独的命令对象中。这减少了它们之间的耦合。
优势:
- 使我们的代码具有可扩展性,因为我们可以在不更改现有代码的情况下添加新命令。
- 减少命令的调用方和接收方之间的耦合。
缺点:
- 增加每个命令的类数
进一步阅读—— Python中的命令方法
参考资料:
如果本文由 苏拉布·库马尔 .如果你喜欢GeekSforgek,并且想贡献自己的力量,你也可以写一篇文章,然后将文章邮寄给评论-team@geeksforgeeks.org.看到你的文章出现在Geeksforgeks主页上,并帮助其他极客。
如果您发现任何不正确的地方,或者您想分享有关上述主题的更多信息,请写评论