Должен ли класс содержать коллекцию?

Неужели у плохого дизайна есть класс, содержащий коллекцию, как в List < > для С#? Почему это и что является лучшим подходом и почему?

EDIT: В частности, у меня есть класс Product и метод класса GetProducts(), который возвращает коллекцию List. Хорошо бы хватать продукты из базы данных, плоского файла или xml... пока не уверен.

Спасибо!

Ответ 1

При обновлении продукта и GetProducts() я думаю, что это может быть не очень хорошо.

Я использую основное правило такого принципа, который опирается на логику, которая является доменом, а не языком, специфическим. Поэтому в вашем случае я бы спросил себя: "В моем продукте содержатся другие актуальные продукты?" Если ответ "да", то сбор продуктов является вполне законным для класса Product. Если не спросить, что на самом деле содержит эти продукты. Магазин может быть?

Существует исключение из этого правила со статическими методами. Если GetProducts() является статическим, то верхняя аргументация не применяется и обычно отлично подходит для использования в классе Product.

Ответ 2

Лично я бы использовал шаблон репозитория:

public class IProductRepository
{
    IEnumerable<Product> GetAll();
}

Затем напишите реализацию:

public class ProductRepository
{
    public IEnumerable<Product> GetAll()
    {
        // Database logic or read from an xml file... etc.
    }
}

Передайте IProductRepository вызывающему (используя контейнер IoC, например, Ninject или Castle Windsor). Затем, при необходимости, вы можете легко высмеивать IProductRepository для тестирования с вызывающим абонентом.

Таким образом, вы сохраняете фактическую модель (Product) отдельно от "что вы можете делать" с продуктами.

Но если Product также необходимо иметь Products (пример: SubProducts), вы можете иметь ICollection<Product> на Product.

Ответ 3

Это нормально. Вы придумали tree или graph

Ответ 4

Это может быть как плохо, так и хорошо, в зависимости от проблемы, которую вы решаете, и если это обобщенный объект или нет. На такие проектные решения могут влиять многие факторы. В конце концов, это неважно хорошего или плохого дизайна, но если это правильный путь, который вы решили пересечь реку.

РЕДАКТИРОВАТЬ № 1

ОК, у меня есть класс под названием product и метод внутри GetProducts, который возвращает List, и я не был уверен, что это правильный подход.

В этом случае я сделаю статический метод Product.GetProducts. Таким образом, когда вы хотите загрузить продукты, вы просто адресуете свой класс Product следующим образом:

IList<Product> products = Product.GetProducts();

Список сам по себе предполагает, что продукт может состоять из разных других продуктов, таких как эти компоненты. Но со статическим методом это, скорее всего, сделает ваш Product класс factory для связанного с продуктом бизнеса.

Ответ 5

Конечно, это нормально. Это вообще разумный способ реализации дерева в ООП-у; a TreeNode должен содержать поле List<TreeNode> m_Children, поэтому node знает, для чего он предназначен для обхода дерева.

Ответ 6

До тех пор, пока он не противоречит основному принципу ответственности, я полагаю, что это не проблема.