Проектирование типовых структур данных / хранилища для Контейнера -> (Контейнер) -> Элемент - PullRequest
1 голос
/ 19 марта 2012

У меня возникла проблема при попытке создать общее хранилище ..

В основном у меня есть следующие 4 объекта

Поддон коробка Посылка Пункт

Верхние 3 - это все контейнеры, которые могут содержать в иерархии все, что ниже, чем он сам. Первоначально было принято, чтобы на поддонах были коробки, в коробках - посылки, в посылках - предметы. Но теперь я хочу, чтобы некоторые «средние» контейнеры можно было пропустить: Например, поддоны содержат посылки, которые содержат предметы (без коробок) EG2, Поддоны содержат предметы (без коробок или предметов).

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

В коде у меня возникают другие проблемы, например, для печати содержимого поддона, изначально было бы:

class Pallet : List<Box> {}
class Box : List<Parcel> {}
class Parcel : List<Item> {}
class Item {}


class Pallet : List<Box>
{
    void Print()
    { 
        foreach (Box b in this)
            foreach (Parcel p in b)
                foreach (Item i in p)
                    //Print
    }
}

Но теперь, так как я не знаю, что будет внутри, я не знаю, как это сделать.

Я надеюсь, что кто-нибудь может дать мне совет по проектированию хорошей структуры данных или метода хранения всего хорошего и эффективного способа. Я мог бы сделать что-то вроде:

class Pallet : List<T>
{
    void Print()
    {
        if (this[0] is Box)
            //do this
        if (this[0] is Parcel)
            //do this, etc
    }
}

Но это кажется ужасно грязным.

Надеюсь, вы увидите, что я пытаюсь сделать.

Ответы [ 3 ]

2 голосов
/ 19 марта 2012

Почему вы не можете просто извлечь каждый контейнер из одного и того же базового класса? Тогда вы можете получить что-то вроде следующего:

public abstract class Container
{
    public abstract void Print();

    public List<Container> Contents { get; set; }
}

public class Box : Container
{
    public override void Print() 
    {
        foreach (Container c in Contents)
            Console.WriteLine("I am a {0}", c.ToString());
    }

}

Это означает, что любой контейнер может содержать ряд других контейнеров. Конечно, вам нужно реализовать некоторую логику для управления этим, вам не нужен ящик, содержащий слишком много посылок, но ящик может содержать другой ящик, если он меньше. Теперь вы бы сказали «но Item должен был бы также наследоваться от COntainer, чтобы содержаться в коробке», и вы были бы правы, но вы все равно можете использовать наследование и простое небольшое изменение:

public interface IContainable { }

public abstract class Container
{
    public virtual void Print() 
    {
        foreach (IContainable c in Contents)
            Console.WriteLine("I am a {0}", c.ToString());
    }

    public List<IContainable> Contents { get; set; }
}

public class Pallet : Container {  }

public class Box : Container, IContainable {  }

public class Item : IContainable { }

Использование этого подхода означает, что Pallet может содержать вещи, но не может содержаться. Item может содержаться, но не является контейнером.

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

1 голос
/ 19 марта 2012

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

Если вы добавляете посылку к поддону, создайте поле для «пустышки», чтобы вставить его, со свойством, которое указывает, что это «пустышка».

Затем вы можете сохранить свою существующую, опрятную структуру. Но также добавили гибкость.

1 голос
/ 19 марта 2012

Но теперь я хочу, чтобы некоторые «средние» контейнеры можно было пропустить

Я бы пересмотрел это. Это выглядит просто, но по сути вы создаете здесь вторую параллельную структуру данных. Он вводит совершенно новый набор ограничений.

Лучшим «обходным путем» может быть предоставление каждому поддону по умолчанию (безымянного) ящика и т. Д.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...