是否只有一个使用对象的模式?

时间:2014-09-15 09:10:42

标签: python c++ design-patterns

假设您要使用类Task2Do的对象表示要执行的任务。这些对象是可运行的,也就是说,它们有一个执行任务doTask的方法。

另一方面,你有这些对象的队列(python中的例子):

a = Task2Do(method1, args1)
b = Task2Do(method1, args2)
c = Task2Do(method2, args3)

pending = [a,b,c]

您想要运行所有pending任务:

for t in pending:
    t.doTask()

可能会有人引入错误,因此同一对象在pending队列中出现两次:

pending = [a,a,c]

您可以保护您的代码:

class Task2Do:
    def __init__(self, target, args):
        self._todo = target
        self._args = args
        self._done = False

    def doTask(self):
        if not self._done: # Protection against double execution
            self._todo(*self._args)
            self._done = True

我的问题是:这是否有名称作为设计模式?我听说有些人在C ++中实现了类似的对象析构函数。

您知道其他类似的模式吗?

3 个答案:

答案 0 :(得分:1)

线程池模式允许您将可调用对象推送到数据容器并在一组专用线程上运行它们。线程池的一个优点是,每次要运行对象时都不必启动线程。运行该对象时,将从容器中删除该对象,以使其不再运行。如果需要额外的逻辑来防止运行对象两次,可以将其添加到将对象添加到线程池的代码或者在对象内部运行的代码中。 一个好的线程池库是CTPL,https://github.com/vit-vit/ctpl

答案 1 :(得分:1)

我能想到的最简单的方法是:

class Task2Do:
    def __init__(self, target, args):
        self._todo = target
        self._args = args

    def doTask(self):
        self._todo(*self._args)
        self._todo = lambda: None
        self._args = ()

看起来比旗帜更清洁。或者,让self._todo在第二次调用时抛出错误。您甚至可以将self._todo设置为None


老实说,任务并不是真正需要上课的。大多数情况下,只有拥有一个功能,它更容易,更惯用。在这种情况下,您可以使用生成器来获得一次性使用:

def task2do(target, *args, **kwargs):
    def iter_run_once():
        yield target(*args, **kwargs)
        raise ValueError("Multiple calls to one-time-use task")

    return iter_run_once().__next__

F = task2do(print, 1, 2, 3)

F()
#>>> 1 2 3

F()
#>>> Traceback (most recent call last):
#>>>   File "", line 14, in <module>
#>>>   File "", line 4, in iter_run_once
#>>> ValueError: Multiple calls to one-time-use task

为了好玩,请注意您也可以这样做:

def task2do(target, *args, **kwargs):
    return (lambda: (yield target(*args, **kwargs)))().__next__

答案 2 :(得分:0)

我不知道这里可以提供哪种设计模式,但是你的类Task2Do可以像这样简化:

class Task2Do:
    def __init__(self, target, args):
        self._todo = [target]
        self._args = args

    def doTask(self):
        while len(self._todo):
            todo = self._todo.pop(0):
            todo(*self._args)

这可以避免_done成员被意外重新设置回True