面向对象设计 - 第一类集合/封装集合是否应该实现集合/IEnumerable 接口

本文关键字:集合 是否 封装 实现 接口 IEnumerable 面向对象设计 一类 | 更新日期: 2023-09-27 18:35:44

我是杰夫·贝(Jeff Bay)的物体健美操练习的粉丝:

http://www.xpteam.com/jeff/writings/objectcalisthenics.rtf

并且我通过创建对象来封装集合的实现以及对对象集合的迭代,从而实现了第一类集合,取得了很好的效果。

这意味着我有一个 EmployeeList 对象,而不是列表。

通常,当我创建这些对象时,我不实现任何集合接口,因此外部用户无法枚举内部集合,因为我认为这是重点。然而,一位同事提出了相反的建议 - 实现ICollect接口以使其更加灵活。

这个重构站点似乎方向相同,尽管它没有完全删除对内部集合的访问:http://sourcemaking.com/refactoring/encapsulate-collection

    // Foreach method
    foreach (var employee in employees)
    {
        if (employee.IsManager)
        {
            managers.Add(employee);
        }
    }
    // Linq method
    managers = employees.Where(e => e.IsManager);

    // Encapsulated iteration method
    managers = employees.GetAllManagers();
    public IEnumerable<Employee> GetAllManagers() // Inside Employees class
    {
        return employees.Where(e => e.IsManager);
    }

我说最后一种方法是有利的吗?例如,你什么时候想通过实现 IEnumerable 来公开你的内部集合?

面向对象设计 - 第一类集合/封装集合是否应该实现集合/IEnumerable 接口

IEnumerable可能是一个不错的选择。您可以拥有Employee对象的私有列表,并将其公开为IEnumerable,以便人们在循环、LINQ 等中使用它。

由于IEnumerable不允许修改正在迭代的集合,因此不必担心EmployeeList使用者更改内部结构。

提供迭代方法并不理想,因为它会破坏 POLA,并且需要使用 API 的程序员付出一些努力才能找到他想要调用的方法。想想看,在 .NET 中永远不会有如下所示的代码。

var list = new List<T>;
foreach (var item in list.GetAllItems())
{
    // Whut? 
}