Я реализовал шаблон состояния из «Банды четырех» в Python, и я хотел бы, чтобы метод entry()
вызывался один раз при первом вызове моего handle
метода. Я знаю, что могу сделать это легко, используя логическое свойство и условие if, но я бы хотел сделать его «невидимым» для пользователя. Так что я возился с декораторами, но я не могу заставить вещи работать с методами классов с наследованием ... Не могли бы вы сказать, что я делаю неправильно, или есть лучшее решение этой проблемы?
Вот мой пример кода: Абстрактный класс State:
class TriggerOnce(object):
def __init__(self, fcall):
self.fcall = fcall
self.triggered = False
def __call__(self, obj, *args, **kwargs):
if not self.triggered:
self.fcall(obj, *args, **kwargs)
self.triggered = True
obj.__call__(*args, **kwargs)
# I know this will trigger more than once, but just to try
def trigger_once(fn, fcall=None):
def trigger(*args, **kwargs):
if fcall:
fcall()
return fn(*args, **kwargs)
return trigger
class State(metaclass=ABCMeta):
@property
def context(self):
return self._context
@context.setter
def context(self, context) -> None:
self._context = context
@abstractmethod
def entry(self) -> None:
pass
@abstractmethod
def handle(self, class_id: int) -> None:
pass
Конкретный класс State:
class PersonState(State):
valid_transitions = [
"DriveForkliftState",
"UnknownState"
]
class_id = [3]
def entry(self) -> None:
self.context.objects_tree.set_update(OBJECT_CLASSES.index("person"), True)
@TriggerOnce(entry)
def handle(self, class_id: int) -> None:
if class_id in self.class_id:
return
new_state = None
for state in self.valid_transitions:
state_class = getattr(importlib.import_module(self.__module__), state)
if class_id in state_class.class_id:
new_state = state_class()
break
if new_state is not None:
self.context.transition_to(new_state)