对象构造/方法重载

时间:2011-08-20 16:54:48

标签: perl moose

我正在寻找有关处理如下情况的简洁,可维护和可测试方法的建议,其中参数的不同组合必须通过对象的方法以不同方式解释:

# Every 2 days.
$event = Event::Recurrence->new( recurs => 'daily', interval => 2 );

# 1st and 2nd day of every 3rd week.
$event = Event::Recurrence->new( recurs => 'weekly',  days => [1, 2], interval => 3 );

# 1st and 2nd day of every 4th month.
$event = Event::Recurrence->new( recurs => 'monthly', days => [1, 2], interval => 4 );

# 1st and 2nd day of the 2nd and 3rd week of every month.
$event = Event::Recurrence->new( recurs => 'monthly', days => [1, 2], weeks => [2, 3], interval => 1 );

# 1st and 2nd day of the 2nd and 3rd week of every year.
$event = Event::Recurrence->new( recurs => 'yearly',  days => [1, 2], weeks => [2, 3], interval => 1 );

# 1st and 2nd day of the 2nd and 3rd week of the 3rd and 4th months of every 5th year.
$event = Event::Recurrence->new( recurs => 'yearly',  days => [1, 2], weeks => [2, 3], months => [3, 4], interval => 5 );

# Do something with the event object.
$set = $event->get_set();
根据构造参数,

get_set()的功能会有所不同。

我不是在寻找实现日期处理的方法 - 我正在使用重复事件来说明问题的类型。相反,我正在寻找关于处理将不同可能的参数组合分配到适当方法的好方法的更一般的信息。我正在使用Moose,所以欢迎Moose / OO模式。

以上示例可以大致分为不同类型的事件:每日,每周,每月和每年。每个参数都会以不同的方式处理剩余的参数,但最终结果将是相同类型的对象 - 一组可以执行某些操作的重复事件(获取开始和结束日期,确定交叉点等)。

因此,

get_set()可以实现一个调度表来处理所有可能的参数组合,为每个参数调用一个单独的方法 - 但这感觉很麻烦。

我可以为不同的重复类型(Event::Recurrence::DailyEvent::Recurrence::Weekly等)创建CodeRef属性以及单独的类,并在构造时为属性分配适当的类时间,类似于this question的公认答案 - 虽然我不确定如何实施。

1 个答案:

答案 0 :(得分:0)

对于每种重复事件,您可能应该有单独的子类,例如: DailyRecurringEvent类,WeeklyRecurringEvent类,MonthlyRecurringEvent类等。

(注意:每日和每周的重复活动可以作为“每n天重复活动”的实例实施,即每日活动n = 1,每周活动n = 7。)

我不会在事件对象上调用->get_set,而是将对象本身视为“事件集”。现在的问题是:您希望在您的集合上支持哪些操作以及您可能需要的其他支持类。

示例:假设您要支持一个操作,该操作从超过某一天的事件集中获取下一个发生的事件。将此操作称为“next_event_after”。为上述每个类(即每日,每周,每月,每年)实现这一点非常简单。

现在你说你希望能够接受事件集的交集。如何将一个名为“EventSetIntersection”的新类表示为一组事件集的交集。交集的操作“next_event_after”可以实现如下:

package EventSetIntersection;

use Moose;
has event_sets => (
  is => 'rw',
  isa => 'Array[EventSets]',
);
sub next_event_after {
  my ($self, $date) = @_;
  return min { $_->next_event_after($date) } @{ $self->event_sets };
}

回想一下,您的原始类是EventSet,因此您可以直接创建交集:

my $weekely_event = WeeklyEvent->new(...);
my $yearly_event = YearlyEvent->new(...);
my $intersection = EventSetIntersection->new( event_sets => [ $weekly, $yearly ]);