Python implements command mode, mediator mode and interpreter mode

2024.06.05

1. Command mode

It encapsulates the request into an object, making it possible to parameterize the client with different requests. The command pattern also supports undo operations.

(1) Command pattern structure

The core of the Command pattern is the relationship between a command object and a receiver object. The command object encapsulates a specific request and contains methods to execute the request. The receiver object is responsible for actually executing the request.

Following is the basic structure of the command pattern:

# 命令对象接口
class Command:
    def execute(self):
        pass

    def undo(self):
        pass

# 具体命令对象类
class ConcreteCommandA(Command):
    def __init__(self, receiver):
        self.receiver = receiver

    def execute(self):
        self.receiver.action_a()

    def undo(self):
        self.receiver.undo_action_a()

class ConcreteCommandB(Command):
    def __init__(self, receiver):
        self.receiver = receiver

    def execute(self):
        self.receiver.action_b()

    def undo(self):
        self.receiver.undo_action_b()

# 接收者对象类
class Receiver:
    def action_a(self):
        print("接收者执行动作A")

    def action_b(self):
        print("接收者执行动作B")

    def undo_action_a(self):
        print("接收者撤销动作A")

    def undo_action_b(self):
        print("接收者撤销动作B")

# 客户端代码
if __name__ == "__main__":
    receiver = Receiver()
    command_a = ConcreteCommandA(receiver)
    command_b = ConcreteCommandB(receiver)

    invoker = Invoker()
    invoker.set_command(command_a)
    invoker.execute_command()

    invoker.set_command(command_b)
    invoker.execute_command()
  • 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.

(2) Application scenarios of command mode

The command mode is applicable to the following scenarios:

  • The sender and receiver of requests need to be decoupled so that they can vary independently.
  • Need to support undo operations.

(3) Advantages of the command mode

  • The Command pattern decouples the sender and receiver of a request so that they can vary independently.
  • Command mode supports undo operations.
  • The command pattern follows the open-closed principle, and new command objects can be easily added to the system without affecting the original code.

(4) Disadvantages of the command mode

  • In the command pattern, there is a circular dependency relationship between the command object and the receiver object, which may lead to circular reference problems.

2. Mediator pattern

It encapsulates the interactions between a series of objects to minimize the coupling between objects. The mediator pattern transfers the interactions between objects to the mediator object, so that the objects no longer directly reference each other.

(1) Structure of the Mediator Pattern

The core of the mediator pattern is the mediator object, which encapsulates the interaction logic between a series of objects. The mediator object usually contains one or more interfaces for communicating with other objects.

Following is the basic structure of the Mediator pattern:

# 中介者接口
class Mediator:
    def send(self, message, colleague):
        pass

# 同事类接口
class Colleague:
    def set_mediator(self, mediator):
        pass

    def send(self, message):
        pass

    def receive(self, message):
        pass

# 具体中介者类
class ConcreteMediator(Mediator):
    def __init__(self):
        self.colleague_a = None
        self.colleague_b = None

    def set_colleague_a(self, colleague_a):
        self.colleague_a = colleague_a

    def set_colleague_b(self, colleague_b):
        self.colleague_b = colleague_b

    def send(self, message, colleague):
        if colleague == self.colleague_a:
            self.colleague_b.receive(message)
        elif colleague == self.colleague_b:
            self.colleague_a.receive(message)

# 具体同事类
class ConcreteColleagueA(Colleague):
    def __init__(self, mediator):
        self.mediator = mediator

    def set_mediator(self, mediator):
        self.mediator = mediator

    def send(self, message):
        self.mediator.send(message, self)

    def receive(self, message):
        print("同事A收到消息:", message)

class ConcreteColleagueB(Colleague):
    def __init__(self, mediator):
        self.mediator = mediator

    def set_mediator(self, mediator):
        self.mediator = mediator

    def send(self, message):
        self.mediator.send(message, self)

    def receive(self, message):
        print("同事B收到消息:", message)

# 客户端代码
if __name__ == "__main__":
    mediator = ConcreteMediator()

    colleague_a = ConcreteColleagueA(mediator)
    colleague_b = ConcreteColleagueB(mediator)

    mediator.set_colleague_a(colleague_a)
    mediator.set_colleague_b(colleague_b)

    colleague_a.send("Hello, colleague B!")
    colleague_b.send("Hi, colleague A!")
  • 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.

(2) Application scenarios of the mediator pattern

The mediator pattern is applicable to the following scenarios:

  • There are complex interactions between a group of objects, resulting in a high degree of coupling between the objects.
  • It is required that the interaction logic between objects can be changed flexibly without modifying the reference relationship between objects.

(3) Advantages of the Mediator Pattern

  • The mediator pattern encapsulates the interaction logic between objects into the mediator object, thereby reducing the coupling between objects to a minimum.
  • The mediator pattern allows the interaction logic between objects to be flexibly changed without modifying the reference relationship between objects.
  • The mediator pattern follows the open-closed principle, and new colleague classes can be easily added to the system without affecting the original code.

(4) Disadvantages of the Mediator Pattern

  • In the mediator pattern, the mediator object usually needs to know all colleague classes, which may cause the mediator object to have too heavy responsibilities.

3. Interpreter mode

It defines the grammar of a language and parses the corresponding statements. The interpreter pattern defines the grammar of the language, maps each rule in the grammar to a class, and then parses the statements recursively.

(1) Structure of the Interpreter Pattern

The core of the Interpreter pattern is the Interpreter class, which encapsulates the logic of interpreting statements. The Interpreter class usually contains one or more interpretation methods for interpreting different parts of the statement.

Following is the basic structure of the Interpreter pattern:

# 抽象表达式类
class AbstractExpression:
    def interpret(self, context):
        pass

# 终结符表达式类
class TerminalExpression(AbstractExpression):
    def interpret(self, context):
        # 解释终结符表达式的逻辑
        pass

# 非终结符表达式类
class NonterminalExpression(AbstractExpression):
    def __init__(self):
        self.expressions = []

    def add_expression(self, expression):
        self.expressions.append(expression)

    def interpret(self, context):
        # 解释非终结符表达式的逻辑
        for expression in self.expressions:
            expression.interpret(context)

# 上下文类
class Context:
    def __init__(self):
        self.input = None
        self.output = None

# 客户端代码
if __name__ == "__main__":
    context = Context()

    # 构建语法树
    expression1 = TerminalExpression()
    expression2 = NonterminalExpression()
    expression3 = TerminalExpression()

    expression2.add_expression(expression1)
    expression2.add_expression(expression3)

    # 解释语句
    expression2.interpret(context)
  • 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.

(2) Application scenarios of the interpreter pattern

The interpreter mode is suitable for the following scenarios:

  • The grammar of a language is relatively simple, and the rules of the grammar can be expressed through classes.
  • A specific language needs to be parsed and executed.

(3) Advantages of the Interpreter Pattern

  • The interpreter pattern encapsulates the logic of interpreting statements into the interpreter class, so that the logic of interpreting statements can be changed flexibly.
  • The interpreter pattern follows the open-closed principle, and new interpreter classes can be easily added to the system without affecting the original code.

(4) Disadvantages of the Interpreter Pattern

  • In the interpreter pattern, the interpreter class usually needs to know all the grammar rules, which may cause the interpreter class to have too much responsibility.