实现非日期驱动的重复

时间:2011-04-01 15:14:38

标签: c# algorithm recurrence

我正在开发一个应用程序,它可以在用户需要对各种设备执行预防性维护时提示用户。每件设备(称之为工具)都有不同的重复模式。有些将基于时间,例如每90天,而其他基于其他因素,如使用。例如,特定工具在签出X次后可能需要PM。

所有工具都分配给个人,因此当该用户登录应用程序时,我需要显示当时需要PM的工具列表。当PM完成后,这些项目从列表中删除,并且在其他情况下,例如日期更改或工具被重新检入婴儿床,将添加工具。

我开始设计将返回此列表的服务方法,并且正在寻找一些帮助来解决我用来解决列表中的项目的方法。对于输入,我将拥有用户的标识符和当前日期。由此我需要查询工具列表并根据它们的重复模式确定PM的最后一次执行时间以及自上次PM以来发生的事件,该项目是否应出现在列表中。

希望这是有道理的。我很欣赏有关如何处理这种逻辑的任何想法和指导。

3 个答案:

答案 0 :(得分:2)

为了结束,我想我会用我的努力结果来更新帖子,虽然我对Brandon和Florian的答案给予了肯定,因为我发送了正确的道路。

我最终得到了一个接口,正如Brandon建议的那样,调用IHaveRecurrence定义如下:

public interface IHaveRecurrence
{
    DateTime? LastOccurrence { get; }
    RecurrenceType RecurrenceType { get; }
    Int32 RecurrenceValue { get; }
    Boolean IsDue();
}

My MaintainableTool(base)类现在实现了这个接口。 IsDue方法是通过委托Recurrence类实现的:

public Boolean IsDue()
{
    return Recurrence.IsDue(this);
}

Recurrence是Florian建议的抽象基类。我有几个子类,例如DailyRecurrence,WeeklyRecurrence等。每个子类对应于RecurrenceType枚举中的一个值,并通过IHaveRecurrence接口实现相应的逻辑,以根据RecurrenceValue和LastOccurrence属性确定PM是否到期。 / p>

Recurrence使用内部RecurrenceFactory类来解析要使用的子类:

internal sealed class RecurrenceFactory
{
    public Recurrence GetRecurrence(RecurrenceType type)
    {
        switch (type)
        {
            case Daily: return new DailyRecurrence;
            :
        }
    }
}

并且重复实施为:

public abstract class Recurrence : IDisposable
{
    public static Boolean IsDue(IHaveRecurrence recurringObj)
    {
        using (var recurrence = RecurrenceFactory.GetRecurrence(recurringObj.RecurrenceType))
        {
            return recurrence.GetIsDue(recurringObj);
        }
    }

    protected abstract Boolean GetIsDue(IHaveRecurrence recurringObj);
}

然后,例如,DailyRecurrence类实现为:

public sealed class DailyRecurrence : Recurrence
{
    protected override Boolean GetIsDue(IHaveRecurrence recurringObj)
    {
        if (recurringObj.LastOccurred.HasValue)
            return recurringObj.LastOccurred.AddDays(recurringObj.RecurrenceValue) <= DateTime.Now;

        return true;
    }
}

我喜欢这个模型,因为它具有高度可扩展性,它封装了解析每个重复发生模式所需的逻辑,并保持业务对象的清洁。

答案 1 :(得分:1)

听起来我觉得每个工具都有自己的逻辑来判断PM是否需要。所以我会用一些enum定义一个IEquipment接口,如下所示:

public enum RecurrenceType
{
    //Values
}

public enum RecurrenceFrequency
{
    //Values
}

public interface IEquipment
{
    bool IsPMRequired();

    RecurrenceType RecurrenceType { get; }
    RecurrenceFrequency RecurrenceFrequency { get; }
    //You may want to choose something other than object, or eliminate this property
    object RecurrenceValue { get; set; } 
}

然后每种类型的设备都会实现接口,并且可以实现确定是否需要PM的逻辑:

public class Tractor : IEquipment
{
    public bool IsPMRequired()
    {
        //Implement logic here specific to a Tractor
        throw new NotImplementedException();
    }

    public RecurrenceType RecurrenceType
    {
        get { throw new NotImplementedException(); }
    }

    public RecurrenceFrequency RecurrenceFrequency
    {
        get { throw new NotImplementedException(); }
    }

    public object RecurrenceValue
    {
        get
        {
            throw new NotImplementedException();
        }
        set
        {
            throw new NotImplementedException();
        }
    }
}

然后你使用这些对象的逻辑就像:

List<IEquipment> equipment = new List<IEquipment>();
//Populate equipment
List<IEquipment> display = equipment.Where(e => e.IsPMRequired()).ToList();
//Display the equipment that needs PM

在您设置常用方法/属性定义的设备中有一个基类也是有意义的。

答案 2 :(得分:1)

我将定义一个类似于此的抽象类Recurrence:

abstract class Recurrence
{
      public abstract bool IsDue(DateTime dateAndTime);
}

现在让Recurrence成为装备的属性。

abstract class Equipment
{
      protected abstract Recurrence PMRecurrence
      {
            get;
      }

      public bool IsPMDue(DateTime dateAndTime)
      {
             return PMRecurrence.IsDue(dateAndTime);
      }
 }

然后,您可以定义Recurs的相应子类,如TimeRecurrence,UsageRecurrence,并将它们的实例分配给设备的适当子类,如Hammer,Tractor,并根据需要实现它们。这应该提供灵活性和可维护性的良好平衡。

祝你好运,看起来像是一项具有挑战性的任务!