Posts 设计模式-命令模式
Post
Cancel

设计模式-命令模式

概念解析

命令模式,能够讲一个请求封装成一个对象,从而能够使用不同的请求把客户端参数化,对请求进行排队或者记录请求日志,可以提供命令的撤销和恢复功能。其核心是将具体的命令和对应的接受者相关联,使得调用方不用关心具体的行动执行者以及如何执行,只要发送正确的命令,就能准确无误地完成相应的任务。命令模式的三个核心角色:

  • 命令(Command):要完成的任务,或要执行的动作,为命令模式的核心角色
  • 接受者(Receiver):任务的具体实施方,或者行动的真实执行者
  • 调度者(Invoker):接收任务并发送命令,对接用户需求并执行内部命令,负责外部用户与内部命令的交互
  • 用户(Client):命令的使用者,即真正用户

命令模式类图如下:

img

其优点在于:

  • 命令的发送者和接受者进行解耦,调用者不需要关心具体的行动以及如何执行
  • 可以方便地增加其他命令

缺点在于:

  • 添加新的命令,需要具体的类去封装,容易导致命令类膨胀

主要的应用场景:

  • 一些消息响应机制,如GUI中的各种按钮的点击命令
  • 需要将请求调用者和请求接受者解耦

设计模板

命令模式的框架如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
from abc import 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 set_command(self, command):
        self.__command = command

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

实例分析

场景说明:模拟游戏中的基本操作:行走和攻击,行走包括上/下/左/右,以及相关的组合命令:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
from abc import ABCMeta, abstractmethod
import time


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

    # 每次移动的步距
    STEP = 5

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

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

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

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

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

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

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

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

    def show_position(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 set_role(self, role):
        self.__role = role

    @abstractmethod
    def execute(self, role):
        pass


class Left(GameCommand):
    """左移命令"""
    def execute(self):
        self._role.left_move()
        self._role.show_position()


class Right(GameCommand):
    """右移命令"""
    def execute(self):
        self._role.right_move()
        self._role.show_position()


class Up(GameCommand):
    """上移命令"""
    def execute(self):
        self._role.up_move()
        self._role.show_position()


class Left(GameCommand):
    """下移命令"""
    def execute(self):
        self._role.down_move()
        self._role.show_position()


class Jump(GameCommand):
    """弹跳命令"""
    def execute(self):
        self._role.jump_move()
        self._role.show_position()
        # 跳起后空中半秒
        time.sleep(0.5)


class Squat(GameCommand):
    """下蹲命令"""
    def execute(self):
        self._role.squat_move()
        self._role.show_position()
        # 下蹲后伏地半秒
        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 add_command(self, command):
        self.__commands.append(command)

    def remove(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 set_command(self, command):
        self.__command = command
        return self

    def action(self):
        if self.__command is not None:
            self.__command.execute()
This post is licensed under CC BY 4.0 by the author.

设计模式-工厂模式

设计模式-享元模式