16.命令模式

定义

  • 将一个请求封装成一个对象,从而让你使用不同的请求把客户端参数化,对请求排队或者记录请求日志,可以提供命令的撤销和恢复功能。
  • 命令模式的最大特点是将具体的命令与对应的接收者相关联(捆绑),使得调用方不用关心具体的行动执行者及如何执行,只要发送正确的命令,就能准确无误地完成相应的任务。就像军队,将军一声令下,士兵就得分秒不差,准确执行。
  • 命令模式是一种高内聚的模式,之所以说是高内聚是因为它把命令封装成对象,并与接收者关联在一起,从而使(命令的)请求者(Invoker)和接收者(Receiver)分离。

命令模式的模型抽象

代码框架

from abc import ABCMeta, abstractmethod  
  
  
# 引入ABCMeta和abstractmethod来定义抽象类和抽象方法  
  
class Command(metaclass=ABCMeta):  
    """命令的抽象类"""  
  
    @abstractmethod  
    def execute(self):  
        pass  
  
  
class CommandImpl(Command):  
    """命令的具体实现类"""  
  
    def __init__(self, receiver):  
        self.__receiver = receiver  
  
    def execute(self):  
        self.__receiver.doSomething()  
  
  
class Receiver:  
    """命令的接收者"""  
  
    def doSomething(self):  
        print("do something...")  
  
  
class Invoker:  
    """调度者"""  
  
    def __init__(self):  
        self.__command = None  
  
    def setCommand(self, command):  
        self.__command = command  
  
    def action(self):  
        if self.__command is not None:  
            self.__command.execute()

类图

模型说明

  • 设计要点
    • 命令模式中主要有四个角色,在设计命令模式时要找到并区分这些角色。
      • 命令(Command):要完成的任务,或要执行的动作,这是命令模式的核心角色。
      • 接收者(Receiver):任务的具体实施方,或行动的真实执行者。
      • 调度者(Invoker):接收任务并发送命令,对接用户的需求并执行内部的命令,负责外部用户与内部命令的交互。
      • 用户(Client):命令的使用者,即真正的用户。
  • 优缺点
    • 优点
      • 对命令的发送者与接收者进行解耦,使得调用方不用关心具体的行动执行者及如何执行,只要发送正确的命令即可。
      • 可以很方便地增加新的命令。
    • 缺点
      • 在一些系统中可能会有很多命令,而每一个命令都需要一个具体的类去封装,容易使命令的类急剧膨胀。

例子

#!/usr/bin/python
# -*- coding: UTF-8 -*-
# Authoer: Spencer.Luo
# Date: 5/18/2018

from abc import ABCMeta, abstractmethod
# 引入ABCMeta和abstractmethod来定义抽象类和抽象方法
import time
# 引入time模块进行时间的控制

class GameRole:
    """游戏的角色"""

    # 每次移动的步距
    STEP = 5

    def __init__(self, name):
        self.__name = name
        self.__x = 0
        self.__y = 0
        self.__z = 0

    def leftMove(self):
        self.__x -= self.STEP

    def rightMove(self):
        self.__x += self.STEP

    def upMove(self):
        self.__y += self.STEP

    def downMove(self):
        self.__y -= self.STEP

    def jumpMove(self):
        self.__z += self.STEP

    def squatMove(self):
        self.__z -= self.STEP

    def attack(self):
        print("%s发动攻击..." % self.__name)

    def showPosition(self):
        print("%s的位置:(x:%s, y:%s, z:%s)" % (self.__name, self.__x, self.__y, self.__z) )

class GameCommand(metaclass=ABCMeta):
    """游戏角色的命令类"""

    def __init__(self, role):
        self._role = role

    def setRole(self, role):
        self._role = role

    @abstractmethod
    def execute(self):
        pass

class Left(GameCommand):
    """左移命令"""

    def execute(self):
        self._role.leftMove()
        self._role.showPosition()

class Right(GameCommand):
    """右移命令"""

    def execute(self):
        self._role.rightMove()
        self._role.showPosition()

class Up(GameCommand):
    """上移命令"""

    def execute(self):
        self._role.upMove()
        self._role.showPosition()

class Down(GameCommand):
    """下移命令"""

    def execute(self):
        self._role.downMove()
        self._role.showPosition()


class Jump(GameCommand):
    """弹跳命令"""

    def execute(self):
        self._role.jumpMove()
        self._role.showPosition()
        # 跳起后空中停留半秒
        time.sleep(0.5)

class Squat(GameCommand):
    """下蹲命令"""

    def execute(self):
        self._role.squatMove()
        self._role.showPosition()
        # 下蹲后伏地半秒
        time.sleep(0.5)


class Attack(GameCommand):
    """攻击命令"""

    def execute(self):
        self._role.attack()

class MacroCommand(GameCommand):
    """宏命令,也就是组合命令"""

    def __init__(self, role = None):
        super().__init__(role)
        self.__commands = []

    def addCommand(self, command):
        # 让所有的命令作用于同一个对象
        self.__commands.append(command)

    def removeCommand(self, command):
        self.__commands.remove(command)

    def execute(self):
        for command in self.__commands:
            command.execute()

class GameInvoker:
    """命令调度者"""

    def __init__(self):
        self.__command = None

    def setCommand(self, command):
        self.__command = command
        return self

    def action(self):
        if self.__command is not None:
            self.__command.execute()

def testGame():
    """在控制台用字符来模拟命令"""
    role = GameRole("常山赵子龙")
    invoker = GameInvoker()
    while True:
        strCmd = input("请输入命令:");
        strCmd = strCmd.upper()
        if (strCmd == "L"):
            invoker.setCommand(Left(role)).action()
        elif (strCmd == "R"):
            invoker.setCommand(Right(role)).action()
        elif (strCmd == "U"):
            invoker.setCommand(Up(role)).action()
        elif (strCmd == "D"):
            invoker.setCommand(Down(role)).action()
        elif (strCmd == "JP"):
            cmd = MacroCommand()
            cmd.addCommand(Jump(role))
            cmd.addCommand(Squat(role))
            invoker.setCommand(cmd).action()
        elif (strCmd == "A"):
            invoker.setCommand(Attack(role)).action()
        elif (strCmd == "LU"):
            cmd = MacroCommand()
            cmd.addCommand(Left(role))
            cmd.addCommand(Up(role))
            invoker.setCommand(cmd).action()
        elif (strCmd == "LD"):
            cmd = MacroCommand()
            cmd.addCommand(Left(role))
            cmd.addCommand(Down(role))
            invoker.setCommand(cmd).action()
        elif (strCmd == "RU"):
            cmd = MacroCommand()
            cmd.addCommand(Right(role))
            cmd.addCommand(Up(role))
            invoker.setCommand(cmd).action()
        elif (strCmd == "RD"):
            cmd = MacroCommand()
            cmd.addCommand(Right(role))
            cmd.addCommand(Down(role))
            invoker.setCommand(cmd).action()
        elif (strCmd == "LA"):
            cmd = MacroCommand()
            cmd.addCommand(Left(role))
            cmd.addCommand(Attack(role))
            invoker.setCommand(cmd).action()
        elif (strCmd == "RA"):
            cmd = MacroCommand()
            cmd.addCommand(Right(role))
            cmd.addCommand(Attack(role))
            invoker.setCommand(cmd).action()
        elif (strCmd == "UA"):
            cmd = MacroCommand()
            cmd.addCommand(Up(role))
            cmd.addCommand(Attack(role))
            invoker.setCommand(cmd).action()
        elif (strCmd == "DA"):
            cmd = MacroCommand()
            cmd.addCommand(Down(role))
            cmd.addCommand(Attack(role))
            invoker.setCommand(cmd).action()
        elif (strCmd == "JA"):
            cmd = MacroCommand()
            cmd.addCommand(Jump(role))
            cmd.addCommand(Attack(role))
            cmd.addCommand(Squat(role))
            invoker.setCommand(cmd).action()
        elif (strCmd == "Q"):
            exit()

testGame()

应用场景

  • 你希望系统发送一个命令(或信号),任务就能得到处理时。如 GUI 中的各种按钮的点击命令,再如自定义一套消息的响应机制。
  • 需要将请求调用者和请求接收者解耦,使得调用者和接收者不直接交互时。
  • 需要将一系列的命令组合成一组操作时,可以使用宏命令的方式。
暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇