вы можете сделать это
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;
}
Использование перечисления является более ограничительным, а это означает, что менее вероятно, что пользователь попытается использовать вашу фабрику с неподдерживаемым типом.
Я считаю, что делать все возможное при определении API, чтобы препятствовать шаблонам использования, которые будут вызывать исключения. Разрешение «Типа» в этом случае открывает миллионы способов вызвать вашу функцию, что приведет к:
throw new Exception("Invalid type");
Использование перечисления устранит это. Единственный способ выдачи перечисления - это если пользователь сделал что-то заметно неправильное.
Фабрики полезны, только если они выполняют настройку или инициализацию ваших объектов, чтобы перевести их в допустимое состояние. Я бы не стал возиться с фабрикой, если бы все, что она делала, - это новые и возвращаемые объекты.
Я бы создал фабрику для каждой иерархии классов. Например:
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
}
}
Если вам нужна надежная фабрика, вы должны создать по одной конкретной фабрике для каждого конкретного типа. Этот класс не следует принципу открытого-закрытого: каждый раз, когда у вас появляется новый конкретный тип, вы должны повторно редактировать этот класс.
ИМХО, лучший подход - использовать наследование, один конкретный заводской класс для каждого конкретного типа.
1116024]
Я бы предпочел использовать общее ограничение по той причине, что наличие перечисления только для указания типа объекта, который вы хотите, кажется мне избыточным, и с использованием типа, как вы описали вы нарушаете принцип Открыто / Закрыто. То, что я сделал бы иначе, чем то, что вы сделали там, - это ограничить ваш тип, чтобы можно было передавать только допустимые типы.
Я приведу пример на C # с использованием дженериков.
public class SimpleFactory
{
public static ITest Create<T>()
where T: ITest, new()
{
return new T();
}
}
Затем вы можете реализовать IConcreteTest с обоими ConcreteTest1 и ConcreteTest2, и вы можете использовать свою фабрику следующим образом:
ConcreteTest1 test1 = SimpleFactory.Create<ConcreteTest1>();
Я думаю, что больше всего меня беспокоит то, что цель фабрики - позволить клиентскому коду создать производный экземпляр объекта, не зная подробностей создаваемого типа (подробнее в частности, подробности о том, как создать экземпляр, но если все сделано правильно, вызывающему не нужно знать какие-либо более тонкие детали, помимо того, что предоставляется базовым классом).
Использование информации о типе, извлеченной из производного типа, по-прежнему требует, чтобы вызывающая сторона имела некоторые подробные знания о том, какой тип он хочет создать, что затрудняет обновление и поддержку. Подставляя тип Enum (или строку, int и т. Д.), Вы можете обновить фабрику без необходимости обновлять вызывающий код, чтобы знать о новых производных типах.
Если вы хотите создавать по типу, вы можете просто использовать Activator.CreateInstance (Type t)
. Оберните его в шаблонный метод, чтобы ограничить его своим интерфейсом, например Create
.