C# 中对象健美操第一类集合规则的示例?

Eho*_*ret 3 c# oop design-patterns solid-principles

我正在玩对象健美操规则,在使用 C# 时,我在查看何时使用第一类集合时遇到了一些麻烦。

我的意思是我几乎看不到什么时候应该使用它,例如很难将该规则应用于 EF DbContext

比方说,我们设计了一个 Board 类。

public class Board
{
    public IList<BoardRow> Rows { get; }
    public IList<BoardColumn> Columns { get; }

    public Board()
    {
        Rows = new List<BoardRow>();
        Columns = new List<BoardColumn>();
    }
}
Run Code Online (Sandbox Code Playgroud)

所以根据这个规则,我们必须把上面的代码变成:

// Is it really that better than just using List<BoardRow>?
public class BoardRowCollection : IEnumerable<BoardRow>
{
    public void Add(BoardRow row) { /*...*/ }
    public void Remove(BoardRow row) { /*...*/ }

    // IEnumerable<BoardRow> Impl goes here...
}

// Is it really that better than just using List<BoardColumn>?
public class BoardColumnCollection : IEnumerable<BoardColumn>
{
    public void Add(BoardColumn column) { /*...*/ }
    public void Remove(BoardColumn column) { /*...*/ }

    // IEnumerable<BoardRow> Impl goes here...
}

public class Board
{
    public BoardRowCollection Rows { get; }
    public BoardColumnCollection Column { get; }

    // Rest of the impl, ctor, etc.
}
Run Code Online (Sandbox Code Playgroud)

当您已经拥有可用于实现目标的基类时,我不确定是否理解这条规则的要点。

也许上面的代码不是最好的,但我想看一个可以阐明该规则目的的示例。

Rom*_*man 5

背景

假设您有一个类,Foo并且出于任何原因需要RowsBoard.

现在Foo需要在Rows. 几天后你需要一个类Buu,它应该在Rows.

双方FooBuu有自己的关于如何找到一个项目的实施Rows

// ...
Foo foo = new Foo(board.getRows());
Buu buu = new Buu(foo.getRows());

BoardRow row5 = foo.find5thRow();
BoardRow row8 = buu.find8thRow();
Run Code Online (Sandbox Code Playgroud)

只有 Collection 本身应该知道如何对其进行操作

对象健美操

这条规则的应用很简单:任何包含集合的类都不应包含其他成员变量。每个集合都包含在它自己的类中,所以现在与集合相关的行为都有一个家。您可能会发现过滤器成为这个新类的一部分。此外,您的新类可以处理诸如将两个组合并或将规则应用于组的每个元素之类的活动。

如果我们的行创建一个头等系列,我们可以它的一个实例传递到FooBoo并调用它的方法:

class Foo {
    RowCollection rowCollection;

    // constructor and more ...

    public BoardRow find5thRow() {
        rowCollection.findByIndex(5);
    }
}
Run Code Online (Sandbox Code Playgroud)

概括

First Class Collection 应该涵盖创建、读取、更新、删除、过滤、合并等操作。传递 First Class Collection 的实例而不是它自己的集合。优点是您只需将方法委托给您的第一类集合,而无需编写操作的新副本。