【发布时间】:2014-06-05 15:43:25
【问题描述】:
在创建班级结构时,我正在努力遵守 Liskov 替换原则。我想在 Day 类中存储一组日历项目。需要有几种不同类型的 CalendarItem,例如:
约会项目
注意事项
轮播项目
它们都有一些共同的功能,这些功能存在于抽象基类 CalendarItem 中:
public abstract class CalendarBaseItem
{
public string Description { get; private set; }
public List<string> Notes { get; private set; }
public TimeSpan StartTime { get; private set; }
public TimeSpan EndTime { get; private set; }
public int ID { get; private set; }
public DateTime date { get; private set; }
code omitted...
}
但例如 RotaItem 有一些额外的功能:
public class RotaItem : CalendarBaseItem
{
public string RotaName { get; private set; }
private bool spansTwoDays;
public bool spanTwoDays()
{
return this.spansTwoDays;
}
}
其他类也添加了自己的逻辑等。
我为我的日课收集了一组 CalendarBaseItem:
List<CalendarBaseItem> calendarItems;
但是在回顾这一点时,我可以看到我违反了 LSP 原则,因为我必须检查并强制转换每个具体类型才能获得我想要的每个子类的功能。
如果有人能建议如何避免这个问题,我将不胜感激。我应该使用组合方法并向每个最终类添加一个 CalendarItem 类,例如
public class RotaItem
{
private CalendarBaseItem baseItem;
public string RotaName { get; private set; }
private bool spansTwoDays;
public RotaItem(baseArgs,rotaArgs)
{
baseItem = new CalendarBaseItem(baseArgs);
}
public bool spanTwoDays()
{
return this.spansTwoDays;
}
}
这里唯一的问题是我需要为我的 Day 类中的每个 Concrete CalendarItem 单独收集一个集合?
【问题讨论】:
-
你的类设计并没有破坏 LSP——具体的类很可能有自己的方法。你的设计实际上是正确的。但是,在使用您的课程时,您很可能是
doing it wrong(tm)。您如何使用这些特定于类的函数? -
谢谢 - 我想我被基类的集合而不是类设计所困。每个具体类都有一个集合会更好吗?日课最终将提供视图,每个具体类都依赖自己的方法来构建视图。目前,我似乎必须进行类型检查才能从我在日课中的当前 List
构建视图。我最初的设计是基于需要添加新的 Concrete 类,所以当前的集合服务于这个目的。 -
非常正确,拥有
if (item is RotaItem) {}是完全有效的(只要您不枚举日历中的所有项目)。如果您打算拥有很多物品和/或只是想要更高级的东西,请查看visitor pattern
标签: c# design-patterns liskov-substitution-principle