2011-08-20 77 views
1

我在寻找的整洁,维护和测试的方式来处理诸如以下,其中不同的参数组合必须以不同的方式由该对象的方法来解释的情况下建议:对象的构造/方法重载

# 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()将根据构造参数的不同而起作用。

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

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

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

我可以用单独的类针对不同复发类型一起创建一个CodeRef属性(Event::Recurrence::DailyEvent::Recurrence::Weekly,等等),并指定相应的类,在施工时间属性,类似于接受的答案this question - 虽然我不确定我会如何实现这一点。

+0

为什么要的方法做不同不同组参数的东西?你有没有尝试过一个系统,可以做循环事件,而不必关心他们的时期?在采用这种思维方式太古怪之前,我会寻找一个更简单的解决方案。 –

+0

@brian d foy:我在使用[DateTime :: Event :: Recurrence](http://search.cpan.org/~fglock/DateTime-Event-Recurrence-0.16/lib/DateTime/Event/Recurrence.pm) ,但它不能按照我喜欢的方式处理一些重复。相反,我使用[DateTime :: Set-> from_recurrence](http://search.cpan.org/~fglock/DateTime-Set-0.31/lib/DateTime/Set.pm)来创建循环事件。我想遵循类似于DateTime :: Event :: Recurrence的模式,其中'days','weeks'具有不同的含义,具体取决于是否存在其他参数。例如,'days'可以表示星期几或一个月中的某一天。 – Martin

回答

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 }; 
} 

回想一下,你原来的班是EventSets,这样你就可以直接创建交集:

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

这与我选择实现的方法类似,但我最终设法将代码分解到这样的程度,以至于不需要单独的类。相反,我有一个'Event :: Recurrence'类,它有'每日','每周','每月'和'年度'的方法。事实证明,这并不像我想的那样混乱 - 事实上,它非常整洁:-) – Martin