Шаблон "фабрика": перечисления или типы?

вы можете сделать это

public static int[] Divisible(int[] array, int target){
    List<Integer> list = new ArrayList<>();
    for (int i = 0; i<array.length; i++){
        if (array[i] % target == 0){
            list.add(array[i]);
        }
    }
    int[] ints = new int[list.size()];
    for (int i = 0; i < ints.length; i++) {
        ints[i] = list.get(i);
    }
    return ints;
}
7
задан Michael Myers 8 May 2009 в 16:57
поделиться

6 ответов

Использование перечисления является более ограничительным, а это означает, что менее вероятно, что пользователь попытается использовать вашу фабрику с неподдерживаемым типом.

Я считаю, что делать все возможное при определении API, чтобы препятствовать шаблонам использования, которые будут вызывать исключения. Разрешение «Типа» в этом случае открывает миллионы способов вызвать вашу функцию, что приведет к:

throw new Exception("Invalid type");

Использование перечисления устранит это. Единственный способ выдачи перечисления - это если пользователь сделал что-то заметно неправильное.

16
ответ дан 6 December 2019 в 06:51
поделиться

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

Я бы создал фабрику для каждой иерархии классов. Например:

public abstract class Vehicle {}
public class Car : Vehicle {}
public class Truck : Vehicle {}

public class VehicleFactory
{
    public Vehicle CreateVehicle<T>() where T : Vehicle
    {
        // Get type of T and delegate creation to private methods
    }
}
4
ответ дан 6 December 2019 в 06:51
поделиться

Если вам нужна надежная фабрика, вы должны создать по одной конкретной фабрике для каждого конкретного типа. Этот класс не следует принципу открытого-закрытого: каждый раз, когда у вас появляется новый конкретный тип, вы должны повторно редактировать этот класс.

ИМХО, лучший подход - использовать наследование, один конкретный заводской класс для каждого конкретного типа.

1116024]

2
ответ дан 6 December 2019 в 06:51
поделиться

Я бы предпочел использовать общее ограничение по той причине, что наличие перечисления только для указания типа объекта, который вы хотите, кажется мне избыточным, и с использованием типа, как вы описали вы нарушаете принцип Открыто / Закрыто. То, что я сделал бы иначе, чем то, что вы сделали там, - это ограничить ваш тип, чтобы можно было передавать только допустимые типы.

Я приведу пример на C # с использованием дженериков.

public class SimpleFactory
{
 public static ITest Create<T>()
    where T: ITest, new()
 {
    return new T();
 }
}

Затем вы можете реализовать IConcreteTest с обоими ConcreteTest1 и ConcreteTest2, и вы можете использовать свою фабрику следующим образом:

ConcreteTest1 test1 = SimpleFactory.Create<ConcreteTest1>();
2
ответ дан 6 December 2019 в 06:51
поделиться

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

Использование информации о типе, извлеченной из производного типа, по-прежнему требует, чтобы вызывающая сторона имела некоторые подробные знания о том, какой тип он хочет создать, что затрудняет обновление и поддержку. Подставляя тип Enum (или строку, int и т. Д.), Вы можете обновить фабрику без необходимости обновлять вызывающий код, чтобы знать о новых производных типах.

1
ответ дан 6 December 2019 в 06:51
поделиться

Если вы хотите создавать по типу, вы можете просто использовать Activator.CreateInstance (Type t) . Оберните его в шаблонный метод, чтобы ограничить его своим интерфейсом, например Create , где T: ITest .

1
ответ дан 6 December 2019 в 06:51
поделиться
Другие вопросы по тегам:

Похожие вопросы: