我当前正在使用一个模块,该模块允许用户通过创建任务对象实例来构建任意任务网络模型(用于离散事件仿真((我的模块提供任务班级(。除其他外,任务还包含描述其完成的影响的逻辑,例如启动另一个任务。通过这种方式,任务类的实例可能是指一个或多个其他实例,并且有可能发生周期性参考/相互递归。
这是我的代码的极其简化的版本:
taskmodule.py
class Task(object):
def __init__(self, name, effect):
self.name = name
self.effect = effect
def execute(task):
task.effect()
taskTest.py
task1 = task("Do the first thing", execute(task2))
task2 = task("Do the second thing", execute(task3))
task3 = task("Do the third thing", execute(task1))
此实现的问题是我在定义了任务2和任务3之前就参考了任务2和任务3。如果我能排除周期性参考,那将不是世界末日 - 这只是重新安排对象实例化的顺序的问题 - 但我相信我应该适应这种可能性。我已经考虑过一些潜在的解决方法 - 大多数都涉及要求用户间接参考任务(即通过某些唯一的标识符值( - 但我想知道是否有更优雅的解决方案涉及巧妙的抽象形式。
确保实例化任务/生成任务网络的过程(如taskTest.py中所示(尽可能简单,是该项目的首要任务,因为那是我模块的用户将花费的东西他们大部分时间都在做。
我尝试搜索,但似乎大多数关于相互递归/周期性参考的主题的问题,而不是类型。
所以,我认为这里的问题是名称和对象正在混合。我可能会使用一个在字典中组织任务对象的结构,并将字符串或枚举用作密钥。这样,您可以在分配之前参考名称。
class TaskManager:
def __init__(self, tasks=None):
self.tasks = tasks or {}
def register(self, name, task):
self.tasks[name] = task
def execute(self, name):
self.tasks[name].effect()
您需要某种占位符对象,该对象可以表示尚不清楚其依赖项的任务。那你可以做
task1 = Task("Do the first thing", [Placeholder()])
task2 = Task("Do the second thing", [execute(task1)])
task3 = Task("Do the third thing", [execute(task2)])
task1.add_dependency(task3)
task1.remove_placeholders()
它需要是Task("...", [Placeholder()])
而不是Task("...", [])
,因为后者代表了一个任务, no 依赖项,您也希望能够表达。
实现这一目标的一种方法是创建一个任务列表对象来管理任务。实现将取决于您,但从本质上讲,您需要列出一系列任务,这些任务是按顺序执行的。如果某些任务会产生进一步的工作(即,一个非返回(,则将将此结果的任务附加到列表中。
显然,这很容易产生一个无限的过程,因此您可能需要考虑要如何处理它,但这会更多地进入UI设计。