Oop 业务实体-列表是否应仅作为只读集合公开?
在尝试集中如何添加项或从业务实体类中删除项时,我已移动到一个模型,其中所有列表仅作为ReadOnlyCollections公开,并提供Add和Remove方法来操作列表中的对象 以下是一个例子:Oop 业务实体-列表是否应仅作为只读集合公开?,oop,design-patterns,business-objects,Oop,Design Patterns,Business Objects,在尝试集中如何添加项或从业务实体类中删除项时,我已移动到一个模型,其中所有列表仅作为ReadOnlyCollections公开,并提供Add和Remove方法来操作列表中的对象 以下是一个例子: public class Course { public string Name{get; set;} } public class Student { private List<Course>_courses = new List<Course>();
public class Course
{
public string Name{get; set;}
}
public class Student
{
private List<Course>_courses = new List<Course>();
public string Name{get; set;}
public ReadOnlyCollection<Course> Courses {
get{ return _courses.AsReadOnly();}
}
public void Add(Course course)
{
if (course != null && _courses.Count <= 3)
{
_courses.Add(course);
}
}
public bool Remove(Course course)
{
bool removed = false;
if (course != null && _courses.Count <= 3)
{
removed = _courses.Remove(course);
}
return removed;
}
}
公共课
{
公共字符串名称{get;set;}
}
公立班学生
{
私人列表_课程=新列表();
公共字符串名称{get;set;}
公共只读集合课程{
获取{return\u courses.AsReadOnly();}
}
公共无效添加(课程)
{
如果(course!=null&&&u courses.Count我想说,当添加/删除需要按照您建议的方式进行控制时,这是一个好主意,例如对于业务规则验证。否则,正如您从前面的代码中所知道的,实际上无法确保执行验证
然而,您可能希望达到的平衡是何时这样做,何时不这样做。对每种类型的集合都这样做似乎有点过头了。然而,如果您不这样做,然后以后需要添加这种把门代码,那么这将是对类的一个突破性更改,这在当时可能是一个问题,也可能不是一个问题
我想另一种方法可能是使用IList
的自定义子代,它的Add()
和Remove()具有通用的门保持代码
通知系统正在发生的事情的方法。类似于在调用这些方法的内部逻辑之前公开一个引发的事件。然后学生
类将提供一个委托或其他内容(很抱歉说得含糊不清,我今天非常紧张)当实例化\u courses
以将业务逻辑应用于事件,并在业务验证失败时取消操作(我想是抛出异常)
根据开发人员的配置,这可能也有点过头了。但至少有了这样一个稍微精心设计的东西,您就可以获得一个通用的实现,可以根据需要随时添加/删除业务验证,而不会破坏更改。是的,这是一个很好的方法,在我看来,您是对的除了装饰你的列表,什么都不做,这比实现你自己的IList要好(因为你节省了很多代码行,即使你失去了迭代课程对象的更优雅的方式)
你可以考虑接收一个验证策略对象,如在将来你可能会有一个新的要求:EX:一个新的学生可以拥有超过3门课程等。
过去我已经做过了,遗憾的是:一个更好的选择是使用<强>不同的类
例如,使用一个行为丰富的Student
域类,该类小心翼翼地保护其对课程的所有权——如果Student对课程负责,则该类不应公开课程所有权——以及一个StudentDataTransferObject
(或ViewModel
),该类提供课程字符串的简单列表(或在需要ID时提供字典)用于填充接口。我通常公开IEnumerable而不是ReadOnlyCollection,因为Count()等都是在运行时类型上进行优化的,因此不会有任何明显的性能损失。