Создавайте разные объекты с одним и тем же базовым типом. Заводской образец?

Мне нужно реализовать пример приложения с несколькими производителями / несколькими потребителями для университетского курса, и мне трудно найти решение следующей проблемы, которая не заставляет меня чувствовать, что я делаю что-то не так;)

Мне нужно реализовать Producer, который производит данный вид Component (CPUComponent, MainboardComponent. Все подклассы общего класса Component). Каждый экземпляр Producer будет производить только определенное количество компонентов одного типа (например, только материнские платы), а затем завершится.

Все Component являются более или менее неизменяемыми объектами (только поля final), и вся логика реализована в общем базовом классе Component (упрощенно ниже)

public abstract class Component implements Serializable
{    
    private final long id;

    public Component(int id) { ... }

    public long getId()
    {
        return id;
    }
}

Подклассы Component просто примитивны, например

public class CPUComponent extends Component
{
    public CPUComponent(long id) { ... }
}

Поскольку языком является Java, я не могу легко решить эту задачу создания объекта с помощью Generics (как я мог бы это сделать в C #, потому что я не могу создавать экземпляры новых объектов с параметрами универсального типа в Java). Итак, я начал внедрять Factory

public interface ComponentFactory {
    Component createComponent(Producer producer, boolean defective);
}

И предоставьте конкретные фабричные реализации для каждого Component типа.

Проблема, с которой я сейчас сталкиваюсь, заключается в том, что когда я хочу сохранить созданные компоненты в моем классе Storage (просто управляю всеми производимыми компонентами для потребителей), мне нужно выяснить точный тип объектов (каждый CPUComponent и т. Д. В нем. собственная полка), но с завода я получаю только Component (базовый тип).

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

Другое решение, которое я могу придумать, - реализовать Producers для каждого типа Component, но я хотел избежать этого.

Может быть, я думаю о том, чтобы все усложнить, и уже полностью перестроил все это. Просто укажите мне правильное направление;)


person maruchinu    schedule 27.11.2011    source источник
comment
Какая разница, которая не позволяет вам использовать дженерики?   -  person Vlad    schedule 27.11.2011
comment
Почему STorage должен знать тип компонента? Что с ними делать? Может ли он вызвать полиморфный метод компонента?   -  person JB Nizet    schedule 27.11.2011
comment
Потребители Components запрашивают конкретный тип компонента (например, 1 материнскую плату), поэтому я хочу хранить их отдельно, а не в одном Collection<Component>   -  person maruchinu    schedule 27.11.2011


Ответы (4)


Исходя из того, что объектно-ориентированный подход предназначен для указания объектам делать что-то за вас, я бы вызвал метод store() для каждого из ваших компонентов (определите это как abstract в вашем базовом классе), передав объект Storage. Ваши подклассы будут реализовывать этот метод своим особым образом и выступать посредником с объектом Storage, чтобы сохранить себя. Если вы сделаете это, то вашему Storage классу не нужно будет знать о различных компонентах, а добавление нового типа Component требует только определения этого класса и никакой дополнительной работы в другом месте.

Я отмечаю, что в вашем вопросе создается впечатление, что ваши подклассы не имеют дополнительных функций, кроме базового класса (если я правильно прочитал). Именно из-за подобных сценариев подклассы должны иметь функциональность, специфичную для их типа. Вы абсолютно правы. instanceof. Если вам нужно его использовать, то часто это указание на то, что вы не используете полную гибкость объектно-ориентированного программирования и / или что ваш объектный анализ неверен.

person Brian Agnew    schedule 27.11.2011

1) Java поддерживает универсальные шаблоны. Вы говорите, что по какой-то причине общей поддержки в Java в этом случае недостаточно? Из вашего описания похоже, что вы можете просто параметризовать класс Producer, используя универсальный тип.

2) Из вашего описания кажется, что Компонент может быть перечислением.

person Vilas    schedule 27.11.2011
comment
Объявление 1) В Java вы не можете создать экземпляр нового объекта параметра универсального типа, поскольку информация о типе недоступна во время выполнения. Объявление 2) Класс Component имеет больше полей, чем показано выше. Я удалил их для простоты, поэтому не думаю, что enum i в данном случае достаточно. - person maruchinu; 27.11.2011

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

Суть в том, что если ваши классы спроектированы правильно, вы сможете делать все, что вам нужно, с помощью базового класса. Класс Storage будет хранить компоненты, а пользователи класса Storage ничего не будут знать о фактическом классе компонентов; только то, что их можно использовать через интерфейс Component.

person Gigi    schedule 27.11.2011

Вы можете хранить свои Component объекты в отдельных списках, например: motherboards = ArrayList<Component>

Вы правы в том, что вам действительно нужно реализовать здесь шаблон Factory.

public class ComponentFactory() {
    public Component getComponent(Integer id, String componentType) {
        if (componentType.equals("motherboard"))
            return new MotherboardComponent(id);
        else if(componentType.equals("cpu"))
            return new CpuComponent(id);
        else
            return null;
    }
}

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

person Alex    schedule 27.11.2011