对象构造/方法重载

发布于 2024-11-30 14:15:04 字数 1874 浏览 1 评论 0原文

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

# 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() 可以实现一个调度表来处理所有可能的参数组合,为每个参数调用一个单独的方法 - 但这感觉很混乱。

我可以创建一个 CodeRef 属性以及不同重复类型的单独类(Event::Recurrence::DailyEvent::Recurrence::Weekly 等),并分配适当的班级构造时的属性,类似于 这个问题 - 尽管我不确定如何实现它。

I'm looking for suggestions on neat, maintainable and testable ways to handle situations such as the following, where different combinations of parameters must be interpreted in different ways by the object's methods:

# 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() will function differently depending on the construction parameters.

I'm not looking for ways to implement the date handling - I'm using recurring events to illustrate the type of problem. Instead, I'm looking for more generic information on good ways to handle dispatching the different possible combinations of parameters to appropriate methods. I'm using Moose, so Moose/OO patterns are welcome.

The above examples can be broadly split into different types of events: daily, weekly, monthly and yearly. Each will handle the remaining parameters differently, but the end result will be the same type of object - a set of recurring events on which certains operations can be performed (getting the start and end dates, determining intersections, and so on).

get_set() could therefore implement a dispatch table to handle all the possible combinations of parameters, calling a separate method for each - but that feels messy.

I could create a CodeRef attribute along with separate classes for the different recurrence types (Event::Recurrence::Daily, Event::Recurrence::Weekly, and so on), and assign the appropriate class to the attribute at construction time, similar to the accepted answer to this question - although I'm not sure how I would implement that.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

一个人练习一个人 2024-12-07 14:15:04

您可能应该为每种重复事件建立单独的子类,例如 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 ]);

You probably should have separate subclasses for each kind of recurring event, e.g. a DailyRecurringEvent class, WeeklyRecurringEvent class, MonthlyRecurringEvent class, etc.

(Note: daily and weekly recurring events could be implemented as instances of an "every n-day recurring event", i.e. n = 1 for daily events and n = 7 for weekly events.)

Instead of calling ->get_set on your event objects, I would treat the objects themselves as "event sets". Now the question is: what operations do you want to support on your sets and what other supporting classes might you need.

An example: Suppose you want to support an operation that gets the next occurring event from an event set beyond a certain day. Call this operation "next_event_after". Implementubg this for each of the above classes (i.e. daily, weekly, monthly, yearly) is pretty straight forward.

Now you said you want to be able to take the intersection of event sets. How about a new class called "EventSetIntersection" which represents the intersection of a collection of event sets. The operation "next_event_after" for an intersection might be implemented something like this:

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

Recall that your original classes were EventSets, so you can create the intersection directly:

my $weekely_event = WeeklyEvent->new(...);
my $yearly_event = YearlyEvent->new(...);
my $intersection = EventSetIntersection->new( event_sets => [ $weekly, $yearly ]);
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文