Фабричный шаблон для времени компиляции - PullRequest
0 голосов
/ 12 июня 2018

Я пытаюсь определить правильный дизайн для этой проблемы

У меня есть три класса Thread, Consumer и Event

public class Thread {
    private Consumer _consumer = new Consumer();
}

public class Consumer {
    private someMethod() {
        Event event = new Event();
        // do something with event 
    }
}

В моем "основном" T создан и егозависимости инкапсулированы

Thread t = new Thread();

Теперь дизайн изменился, и нам нужно несколько Consumer с, и каждая из них должна создать свой Event.Код одинаков для всех, поэтому мне не нужно менять Consumer.

Я попытался сделать это с помощью дженериков, так как, похоже, это простой и понятный способ.Однако похоже, что невозможно использовать new для универсального типа.(Введено в заблуждение шаблонами C ++)

public class Thread<T extends Event> {
    private Consumer _c = new Consumer<T>();
}

public class Consumer<T extends Event> {
    private someMethod() {
        Event event = new T();
    }
}

Мой другой вариант - передать какую-то фабрику времени компиляции

public interface IEventFactory {
    public Event create();
}

public class EventFactory implements IEventFactory{
    public Event create() {
        return new Event1();
    }
}

public class Thread {
    private Consumer _consumer;

    public Thread (IEventFactory _factory) {
        _consumer = new Consumer(_factory);
    }
}

public class Consumer {
    private IEventFactory _factory;

    public C(IEventFactory factory) {
        _factory = factory;
    }

    private someMethod() {
        Event event = _factory.create();
    }
}

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

1 Ответ

0 голосов
/ 12 июня 2018

Фабрика не добавляет ничего, кроме эталона здесь.Вы можете сделать то же самое с помощью ссылки на метод: передать конструктор Event в конструктор Consumer.Для этого используйте функциональный интерфейс Supplier.

public class Consumer<T extends Event> {
    private final Supplier<T> eventConstructor;

    public Consumer(final Supplier<T> eventConstructor) {
        this.eventConstructor = eventConstructor;
    }

    private void someMethod() {
        final T event = eventConstructor.get();
    }
}

Вы можете распространять конструктор вверх по Thread:

class Thread<T extends Event> {
    private Consumer<T> consumer;

    public Thread(final Supplier<T> eventConstructor) {
        this.consumer = new Consumer<>(eventConstructor);
    }
}

Пример использования:

Thread<Event1> thr = new Thread<>(Event1::new);

Это также будет работать, если определенные события имеют параметры конструктора, например:

Thread<Event2> thr2 = new Thread<>(() -> new Event2("some default"));
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...