Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/oop/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/design-patterns/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Oop 业务实体-列表是否应仅作为只读集合公开?_Oop_Design Patterns_Business Objects - Fatal编程技术网

Oop 业务实体-列表是否应仅作为只读集合公开?

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>();

在尝试集中如何添加项或从业务实体类中删除项时,我已移动到一个模型,其中所有列表仅作为ReadOnlyCollections公开,并提供Add和Remove方法来操作列表中的对象

以下是一个例子:

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()等都是在运行时类型上进行优化的,因此不会有任何明显的性能损失。