【发布时间】:2018-06-28 09:20:00
【问题描述】:
我正在尝试使用计时器类编写观察者模式,该计时器类以给定的时间间隔调用其订阅者。一直在尝试理解 Perl6 中的 Promise 概念。
class Timer does Observable
{
has Promise $!p;
has Int $!interval;
has Bool $!active = False;
submethod BUILD(Int :$!interval) {}
method start {
$!p = Promise.start( {
$!active = True;
loop {
sleep($!interval);
@!action_listeners>>.actionPerformed(ActionEvent.new);
if !$!active {$!p.keep}
}
});
}
method stop {
$!active = False;
}
}
观察者角色只是有一个包含订阅者的数组。当然,我应该创建一个方法来更新角色内的所有订阅者。
role Observable {
has ActionListener @!action_listeners;
method addActionListener(ActionListener $al){
@!action_listeners.push($al);
}
method removeActionListener{
@!action_listeners.pop;
}
}
ActionListener 角色只有一个 actionPerformed 方法。 ActionEvent 类可能不是必需的,目前它只是一个空类。
role ActionListener
{
method actionPerformed(ActionEvent $e) { ... }
}
从脚本运行:
my Subscriber $s = Subscriber.new;
my Timer $t = Timer.new(interval => 1);
$t.start;
$t.addActionListener($s);
$t.addActionListener(Subscriber.new);
.... #doing stuff that lasts for a while
$t.stop;
订阅者类实现 ActionListener 角色(有一个名为 actionPerformed 的方法)。
虽然这工作正常:订阅者的 actionPerformed 方法被调用,直到我调用计时器的 stop 方法。虽然没有适当的方法来删除给定的订阅者。另外我想知道是否有更好的方法来保持/打破承诺,从外部给定代码循环不定式。
我基本上想知道我是否会错过 Perl6 的内置功能?我是在重新发明轮子吗?
【问题讨论】:
-
如果相关,您可以添加
ActionListener的代码吗?此外,loop永远循环... -
当然 ActionListener 是一个简单的角色,定义了一个方法 (actionPerformed) 。打破循环的方法是遵守承诺(通过将 $!active 设置为 True)。同意这不是一个特别好的阻止它的方法。您是否建议循环仍在运行,即使调用它的 Promise 已被保留?
-
并非如此。我没有看到你在远处做动作,从其他函数中设置一个类变量。为什么不使用 stop 来信守承诺,而不是设置该变量?如果没有更多的任务要听,你就不能遵守承诺吗?
-
当数组@!action_listners.elems == 0 时结束承诺,当然是一种选择。虽然在添加动作监听器之前开始承诺,但会立即结束。
-
my $p = Promise.new; $p.then({ say 2 }); say 1; $p.keep;12如果你真的想了解 Perl 6 中的 Promises,暂时忘记start方法,因为它实际上只是简写形式:method start (&code) { my $p = Promise.new; $*SCHEDULER.cue({$p.keep(code())}); $p }(那里有一些区别,但这基本上就是它的作用)
标签: concurrency observer-pattern raku