У этого метода есть несколько недостатков.
Во-первых, когда класс, переданный в getShape, требует аргумента конструктора, .newInstance завершится ошибкой. Например:
public class Circle {
public Circle(int diameter) {
//something
}
}
Вы можете получить отражение, используя getConstructor
и выяснить, какие аргументы передать, но это сложно и подвержено ошибкам. И вы теряете безопасность типов во время компиляции. И как класс фабрики узнает, какие значения передать диаметру?
Одним из преимуществ шаблона проектирования фабрики является то, что вызывающая сторона не должна знать, какой класс реализации используется при вызове. Возьмите следующий пример:
public class ShapeFactory {
public Shape getCircle(int diameter){
return new Circle(int diameter);
}
}
Когда вы вызываете этот метод, вызывающая программа не нуждается в зависимости от класса Circle:
Shape s = ShapeFactory().getCircle(10);
s.draw();
Таким образом, только ShapeFactory
зависит от Circle
. Поэтому, когда вы изменяете или заменяете класс Circle, нужно изменить только ShapeFactory
.
Чтобы создать совместимую с OCP программу для фигур, мы могли бы заменить ShapeFactory средой для внедрения зависимостей. Приведенный ниже код является псевдокодом, который показывает, как это может работать
// define the classes
class Circle {}
class Square {}
// for every class, provide a factory method. These do not have to exist inside a factory class.
public Circle createCircle() {
return new Circle(10)
}
public Circle createSquare() {
return new Square(42, 5)
}
public class Painter {
//when a class requires an instance of the Circle class, the dependency injection framework will find `createCircle`, call it and add the result as an argument here.
public Painter(Circle circle) {
circle.draw();
}
}
//when you need a painter object, we don't create it yourself but let the dependency framework do the heavy lifting
Painter p = dependencyframework.getInstanceOf(Painter.class)
Существует много Java структур внедрения зависимостей, но все они работают примерно так.
Эти платформы выполняют точные действия То же самое, что вы предлагаете (такие вещи, как newInstance
и getConstructor
, но их гораздо больше), они просто скрывают всю сложность отражения.