Организация Factory method

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

Структура проекта выглядит сейчас примерно так:

Интерфейс посредника

public interface ForkMediator {
void appendFork(ForkedObject forkedObject); //добавление объекта к посреднику
ForkedObject[] getForkData(ForkedObject forkedObject); //вернуть все объекты связанные с forkedObject
}

Интерфейс объектов соединяемых посредником

public interface ForkedObject{
double getPositive();
double getNegative();
double getJPositive();
double getJNegative();
void Run();

}

Конечному пользователю я не хочу предоставлять знание о том, что ForkedObject используют ForkMediator. ForkMediator имеет разную логику для различного количества добавленных к нему ForkedObject. Т.е если ForkMediator следит за 2 объектами, то его логика принципиально отличается от логики ForkMediator, который следит за 3 объектами

Я хочу предоставить пользователю интерфейс ForkObjectsFactory и некоторый набор классов конкретных фабрик: TwoForkObjects (создает 2 объекта и посредника для них), ThreeForkObjects(создает три объекта и посредника для них). В целом количество фабрик будет не очень большим.

Проблема в следующем: Все конкретные ForkObject имеют 2 обязательных параметра, мне в голову приходит только такая реализация фабрики для создания этих объектов

Интерфейс фабрики

public interface ForkFactory {
     ForkedObject[] getObjects();
}

Конкретный класс фабрики возвращающей массив из 2 ForkedObject связанных посредником

public class TwoForkFactory implements ForkFactory {

    private Fork[] forks=new Fork[2];

    public TwoForkFactory(double field1Fork1, double field2Fork1,double field1Fork2, double field2Fork2){
        ForkMediator twoForkMediator=new TwoForkMediator();
        forks[0]=new Fork(field1Fork1, field2Fork1, twoForkMediator);
        forks[1]=new Fork(field1Fork2, field2Fork2, twoForkMediator);
    }

    @Override
    public ForkedObject[] getObjects() {
        return forkPipelines;
    }

Вызов в пользовательском коде

ForkFactory factory= new TwoForkFactory (1.0, 2.0, 1.1, 2.5);
ForkedObject[] forkObjects=factory.getObjects();
forkObjects[0].Run(); //в этом методе посредник передает данные между forkObjects

Может быть есть более аккуратное решение, чтобы не передавать в конструктор TwoForkFactory 4 параметра (а для ThreeForkFactory их уже станет 6)?


Ответы (1 шт):

Автор решения: Дмитрий

По описанию это выглядит странно. Если вы сможете выложить код со всеми указанными классами, я думаю, найдется решение на много проще описанного. Кроме того, GoF - это не готовые решения и тем более не ответ на все вопросы. Адаптировать GoF под текущую задачу нужно самому. Зачастую необходимо скручивать гибрид из нескольких паттернов. В данном случае вам нужен фабричный метод, который создает медиаторы. Канонически это отдельные классы (я имею в виду классы для реализации самого фабричного метода). Практически так уже никто не пишет. Для реализации фабричного метода используют статический метод в классе-родителе (интерфейсе), возвращающий переменную типа самого себя. Посмотрите в джаве на лист или сет, тем есть метод of() или в спринге Page.of(). никаких дополнительных классов. Что касается логики инициализации и определения , что именно создавать зависит только от вас. Посему то, что у вас называется фабрики, вообще не нужны. я сделал ForkMediator абстрактным классом просто для того, чтобы реализовать приватный метод. инициализирующий массивы. вы можете вывести интерфейс. пеоскольку я не понял логики преобразования массива Fork в ForkedObject, я возвращаю вам массив Fork. Дальше все просто. Привожу класс ForkMediator и клиентский код.

import java.util.ArrayList;
import java.util.List;

public abstract class ForkMediator {

    public static Fork[] of(double ... args){
        switch(args.length/2){
            case 2: return createFork(new TwoForkMediator(), args);
        }
    }

    private Fork[] createFork (ForkMediator forkMediator, double ... args){
        final List<Fork> forks = new ArrayList<>();
        for (int i = 1; i < args.length; i+=2) 
            forks.add(new Fork(args[i-1], args[i], forkMediator));
        return forks.toArray(new Fork[forks.size()]);
    }

    abstract void appendFork(ForkedObject forkedObject); //добавление объекта к посреднику

    abstract ForkedObject[] getForkData(ForkedObject forkedObject); //вернуть все объекты связанные с forkedObject
}

//вызов из клиента
Fork[] result = ForkMediator.of(1.0, 2.0, 1.1, 2.5);

опять же, если покажете весь код (можете на гите), то думаю, что решение будет другое

→ Ссылка