提问人:Gonen I 提问时间:4/19/2023 更新时间:4/19/2023 访问量:43
无双重调度的访客模式
Visitor pattern without double dispatch
问:
最近,我遇到了一个代码片段,它演示了没有双重调度的修改访客模式。
他们使用运行时类来编写访问函数名称,这允许他们将 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()
答: 暂无答案
评论