文章

设计模式-命令模式

应用场景

假设在编写一个UI框架, 框架中包含一个按钮对象Button, 当点击按钮时则会执行一些指令.

为了能够实现框架与功能的解耦, 通常便会使用命令模式.

  • 按钮点击时会调用命令接口的执行命令
  • 实现接口的对象则依靠多态指派
  • 实现接口的实际指令对象仅负责将指令派发至具体的功能实现类
  • 最终由实现类完成指令
classDiagram
    class Button{
        click()
    }
    class Command{
        <<interface>>
        execute()
    }
    class AddCommand{
        execute()
    }
    class AddService{
        addSomething()
    }
    Button *--> Command
    AddCommand --|> Command
    AddCommand --> AddService

通过这个结构可以看出来, 框架中的Button对于具体业务AddService是完全隔离的.

业务本身不依赖任何框架, 也就是可以对接任何框架

AddCommand则是用来链接框架和具体业务的派发对象. 当需要更换框架的时候也只需要换个派发对象也就是了.

简单的python实现:

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
import abc


# Framework
class Command(abc.ABC):

    @abc.abstractmethod
    def execute(self):
        pass


class UIControl(abc.ABC):

    @abc.abstractmethod
    def draw(self):
        pass

    @abc.abstractmethod
    def action(self):
        pass


class Button(UIControl):

    def __init__(self, cmd: Command = None):
        self.__cmd = cmd

    def draw(self):
        print("draw Button")

    def click(self):
        self.action()

    def action(self):
        if self.command:
            self.command.execute()

    @property
    def command(self):
        return self.__cmd

    @command.setter
    def command(self, value):
        if isinstance(value, Command):
            self.__cmd = value


# Project using Framework above.
class AddButton(Button):

    def __init__(self):
        super().__init__(AddCommand())

    def draw(self):
        print("draw add button.")


class Service(abc.ABC):

    @abc.abstractmethod
    def perform(self):
        pass


class AddService(Service):

    def perform(self):
        self.__add_somethine()

    def __add_somethine(self):
        print("add something to somewhere...")


class BasicCommand(Command):

    def __init__(self, service: Service):
        self.__service = service

    def execute(self):
        self.__service.perform()


class AddCommand(BasicCommand):

    def __init__(self):
        super().__init__(AddService())


if __name__ == "__main__":
    btn = AddButton()
    btn.draw()
    btn.click()

本文由作者按照 CC BY 4.0 进行授权