定义
将请求封装成对象,以便使用不同的请求、队列或者日志来参数化其他对象。命令模式支持可撤销的操作。
优点
命令模式将发出请求的对象和执行请求的对象解耦。在被解耦的两者之间通过命令对象进行沟通,命令对象封装了接收者的一个或者一组动作。
一个命令对象通过在特定的接收者上绑定一组动作来封装一个请求。命令对象将动作和接收者包进对象中,这个对象只暴露一个execute()方法。
python代码如下
from abc import abstractmethod
from enum import Enum
class Command:
def __init__(self):
pass
@abstractmethod
def execute(self):
pass
@abstractmethod
def undo(self):
pass
class CeilingFanSpeed(Enum):
HIGH = 3
MEDIUM = 2
LOW = 1
OFF = 0
class CeilingFan:
def __init__(self,location):
self.location = location
self.speed = CeilingFanSpeed.OFF
def high(self):
self.speed = CeilingFanSpeed.HIGH
print(self.location+":celling fan set high speed!")
def medium(self):
self.speed = CeilingFanSpeed.MEDIUM
print(self.location+":celling fan set medium speed!")
def low(self):
self.speed = CeilingFanSpeed.LOW
print(self.location + ":celling fan set low speed!")
def off(self):
self.speed = CeilingFanSpeed.OFF
print(self.location + ":celling fan set off!")
def get_speed(self):
return self.speed
class CeilingFanHighCommand(Command):
def __init__(self,ceiling_fan):
self.ceiling_fan = ceiling_fan
self.prev_speed = None
def execute(self):
self.prev_speed = self.ceiling_fan.get_speed()
self.ceiling_fan.high()
def undo(self):
if self.prev_speed == CeilingFanSpeed.LOW:
self.ceiling_fan.low()
elif self.prev_speed == CeilingFanSpeed.MEDIUM:
self.ceiling_fan.medium()
elif self.prev_speed == CeilingFanSpeed.HIGH:
self.ceiling_fan.high()
elif self.prev_speed == CeilingFanSpeed.OFF:
self.ceiling_fan.off()
class CeilingFanMediumCommand(Command):
def __init__(self,ceiling_fan):
self.ceiling_fan = ceiling_fan
self.prev_speed = None
def execute(self):
self.prev_speed = self.ceiling_fan.get_speed()
self.ceiling_fan.medium()
def undo(self):
if self.prev_speed == CeilingFanSpeed.LOW:
self.ceiling_fan.low()
elif self.prev_speed == CeilingFanSpeed.MEDIUM:
self.ceiling_fan.medium()
elif self.prev_speed == CeilingFanSpeed.HIGH:
self.ceiling_fan.high()
elif self.prev_speed == CeilingFanSpeed.OFF:
self.ceiling_fan.off()
class CeilingFanLowCommand(Command):
def __init__(self,ceiling_fan):
self.ceiling_fan = ceiling_fan
self.prev_speed = None
def execute(self):
self.prev_speed = self.ceiling_fan.get_speed()
self.ceiling_fan.low()
def undo(self):
if self.prev_speed == CeilingFanSpeed.LOW:
self.ceiling_fan.low()
elif self.prev_speed == CeilingFanSpeed.MEDIUM:
self.ceiling_fan.medium()
elif self.prev_speed == CeilingFanSpeed.HIGH:
self.ceiling_fan.high()
elif self.prev_speed == CeilingFanSpeed.OFF:
self.ceiling_fan.off()
class CeilingFanOffCommand(Command):
def __init__(self,ceiling_fan):
self.ceiling_fan = ceiling_fan
self.prev_speed = None
def execute(self):
self.prev_speed = self.ceiling_fan.get_speed()
self.ceiling_fan.off()
def undo(self):
if self.prev_speed == CeilingFanSpeed.LOW:
self.ceiling_fan.low()
elif self.prev_speed == CeilingFanSpeed.MEDIUM:
self.ceiling_fan.medium()
elif self.prev_speed == CeilingFanSpeed.HIGH:
self.ceiling_fan.high()
elif self.prev_speed == CeilingFanSpeed.OFF:
self.ceiling_fan.off()
class Light:
def __init__(self,location):
self.location = location
def on(self):
print(self.location+":light on")
def off(self):
print(self.location+":light off")
class LightOnCommand(Command):
def __init__(self,light):
self.light = light
def execute(self):
self.light.on()
def undo(self):
self.light.off()
class LightOffCommand(Command):
def __init__(self, light):
self.light = light
def execute(self):
self.light.off()
def undo(self):
self.light.on()
class Stereo:
def __init__(self,location):
self.location = location
def on(self):
print(self.location+":stereo on")
def off(self):
print(self.location+":stereo off")
def set_cd(self):
print("stereo set CD")
def set_volume(self,volume):
print("stereo set volume to:"+str(volume))
class StereoOnCommand(Command):
def __init__(self,stereo):
self.stereo = stereo
def execute(self):
self.stereo.on()
self.stereo.set_cd()
self.stereo.set_volume(20)
def undo(self):
self.stereo.off()
class StereoOffCommand(Command):
def __init__(self,stereo):
self.stereo = stereo
def execute(self):
self.stereo.off()
def undo(self):
self.stereo.on()
class NoCommand(Command):
def __init__(self):
pass
def execute(self):
print("NoCommand execute")
def undo(self):
print("NoCommand undo")
class RemoteControl:
def __init__(self):
self.on_commands = []
self.off_commands = []
self.undo_commands = NoCommand()
for i in range(7):
self.on_commands.append(NoCommand())
self.off_commands.append(NoCommand())
def set_command(self,slot,on_command,off_command):
self.on_commands[slot] = on_command
self.off_commands[slot] = off_command
def on_button_pressed(self,slot):
self.on_commands[slot].execute()
self.undo_commands = self.on_commands[slot]
def off_button_pressed(self,slot):
self.off_commands[slot].execute()
self.undo_commands = self.off_commands[slot]
def undo_button_pressed(self):
self.undo_commands.undo()
def test_command():
remote_control = RemoteControl()
light = Light("Living room")
light_on_cmd = LightOnCommand(light)
light_off_cmd = LightOffCommand(light)
remote_control.set_command(0,light_on_cmd,light_off_cmd)
remote_control.on_button_pressed(0)
remote_control.off_button_pressed(0)
stereo = Stereo("Living room")
stereo_on_cmd = StereoOnCommand(stereo)
stereo_off_cmd = StereoOffCommand(stereo)
remote_control.set_command(1, stereo_on_cmd, stereo_off_cmd)
remote_control.on_button_pressed(1)
remote_control.off_button_pressed(1)
def test_command2():
remote_control = RemoteControl()
ceiling_fan = CeilingFan("Living room")
ceiling_fan_high_cmd = CeilingFanHighCommand(ceiling_fan)
ceiling_fan_medium_cmd = CeilingFanMediumCommand(ceiling_fan)
ceiling_fan_low_cmd = CeilingFanLowCommand(ceiling_fan)
ceiling_fan_off_cmd = CeilingFanOffCommand(ceiling_fan)
remote_control.set_command(0, ceiling_fan_low_cmd, ceiling_fan_off_cmd)
remote_control.set_command(1, ceiling_fan_medium_cmd, ceiling_fan_off_cmd)
remote_control.set_command(2, ceiling_fan_high_cmd, ceiling_fan_off_cmd)
remote_control.on_button_pressed(0)
remote_control.on_button_pressed(1)
# remote_control.undo_button_pressed()
# print("")
# remote_control.off_button_pressed(1)
remote_control.on_button_pressed(2)
remote_control.undo_button_pressed()
remote_control.off_button_pressed(2)
if __name__ == "__main__":
test_command2()