无双重调度的访客模式

Visitor pattern without double dispatch

提问人:Gonen I 提问时间:4/19/2023 更新时间:4/19/2023 访问量:43

问:

最近,我遇到了一个代码片段,它演示了没有双重调度的修改访客模式。

他们使用运行时类来编写访问函数名称,这允许他们将 accept 函数移动到数据类的基类中,然后通过在访问器中添加通用访问函数来完全替换它。

我想在 Java 和 C# 中使用反射可以做同样的事情。

这种方法的优点和缺点是什么?

"""Example of a modified visitor design pattern using runtime info instead of double dispatch"""
from __future__ import annotations # enable postponed evaluation for cyclic reference classes
from abc import ABC
from abc import abstractmethod
from typing import List

class CursorVisitor(ABC):
    def visit(self, cursor: ICursor) -> None:
        visit_func_name = f"visit_{type(cursor).__name__}"
        visit_func = getattr(self, visit_func_name)
        visit_func(cursor)        
    @abstractmethod
    def visit_Cursor2D(self, cursor: Cursor2D) -> None:
        pass
    @abstractmethod
    def visit_Cursor3D(self, cursor: Cursor3D) -> None:
        pass

class ICursor(ABC):
    @abstractmethod
    def print(self) -> None:
        pass

class Cursor2D(ICursor):
    def __init__(self, x: int, y: int) -> None:
        self._x = x
        self._y = y
    def move(self, dx: int, dy: int) -> None:
        self._x += dx
        self._y += dy
    def print(self) -> None:
        print("Cursor2D(", self._x, ",", self._y, ")")

class Cursor3D(ICursor):
    def __init__(self, x: int, y: int, z:int) -> None:
        self._x = x
        self._y = y
        self._z = z
    def move(self, dx: int, dy: int, dz: int) -> None:
        self._x += dx
        self._y += dy
        self._z += dz
    def print(self) -> None:
        print("Cursor3D(", self._x, ",", self._y, ",", self._z,")")

class CursorMoveVisitor(CursorVisitor):
    def __init__(self, dx: int, dy: int, dz: int) -> None:
        self._dx = dx
        self._dy = dy
        self._dz = dz
    def visit_Cursor2D(self, cursor: Cursor2D) -> None:
        cursor.move(self._dx, self._dy)
    def visit_Cursor3D(self, cursor: Cursor3D) -> None:
        cursor.move(self._dx, self._dy, self._dz)

class CursorPrintVisitor(CursorVisitor):
    def visit_Cursor2D(self, cursor: Cursor2D) -> None:
        cursor.print()
    def visit_Cursor3D(self, cursor: Cursor3D) -> None:
        cursor.print()

def demo_use_of_visitor():
    cursor_list: List[ICursor] = []
    cursor_list.append(Cursor2D(5,5))
    cursor_list.append(Cursor3D(6,6,7))
    for cursor in cursor_list:
        move_visitor:CursorMoveVisitor = CursorMoveVisitor(1,1,1)
        move_visitor.visit(cursor)
        print_visitor:CursorPrintVisitor = CursorPrintVisitor()
        print_visitor.visit(cursor)



demo_use_of_visitor()
python 设计 反射 访客模式

评论


答: 暂无答案