Ваше решение не является оптимальным, потому что: 1) вам нужно создать специальные конструкторы для ваших конкретных Shape
s, и вы потеряете проверку типа (во время компиляции) параметров.2) Метод init
конкретного завода подвержен ошибкам.
Вот что я бы сделал.Бетонный завод должен нести параметры конкретных Shape
s конструкторов, но не как неопределенные строки (если вы получаете строки из пользовательского ввода, преобразуйте их до создания конкретного завода):
public interface ShapeFactory {
public Shape make(String shapeType);
}
public class ShapeFactoryImpl implements ShapeFactory {
private int circleRadius;
private int rectangleLength;
private int rectangleBreadth;
public ShapeFactoryImpl(int circleRadius, int rectangleLength, int rectangleBreadth){
this.circleRadius = circleRadius;
this.rectangleLength = rectangleLength;
this.rectangleBreadth = rectangleBreadth;
}
public Shape make(String shapeType) {
switch (shapeType) {
case "Circle": return new Circle(this.circleRadius);
case "Rectangle": return new Rectangle(this.rectangleLength, this.rectangleBreadth);
default: throw new Exception("...");
}
}
}
Клиент не должен знать конкретный ShapeFactory
, который он использует, и не должен беспокоиться о конкретном Shape
, который он получает.Зависимость инвертирована: ключевую роль играют абстракции, а не детали.Но если количество возможных фигур увеличится, вы получите конструктор с множеством похожих параметров.Вот еще одно решение:
public class ShapeFactoryImpl implements ShapeFactory {
private Shape circle;
private Shape rectangle;
public ShapeFactoryImpl(Circle circle, Rectangle rectangle){
this.circle = circle;
this.rectangle = rectangle;
}
public Shape make(String shapeType) {
switch (shapeType) {
case "Circle": return this.circle.clone();
case "Rectangle": return this.rectangle.clone();
default: throw new Exception("...");
}
}
}
Это лучше, потому что вы не будете смешивать параметры: каждый конкретный Shape
содержит свои параметры.Если вы хотите сделать его более гибким, вы можете использовать карту, чтобы переместить ответственность за переход с конкретного завода:
public class ShapeFactoryImpl implements ShapeFactory {
private Map<String, Shape> shapeByType;
public ShapeFactoryImpl(Map<String, Shape> shapeByType){
this.shapeByType = shapeByType;
}
public Shape make(String shapeType) {
Shape shape = this.shapeByType.get(Type).clone();
if (shape == null) {
throw new Exception("...");
}
return shape;
}
}
Я бы даже использовал enum
для типов фигур вместострока и EnumMap
для управления коммутатором:
public class ShapeFactoryImpl implements ShapeFactory {
private EnumMap<ShapeType, Shape> shapeByType;
public ShapeFactoryImpl(Map<ShapeType, Shape> shapeByType){
this.shapeByType = shapeByType;
}
public Shape make(ShapeType shapeType) {
return this.shapeByType.get(Type).clone();
}
}
Клиент должен знать интерфейс Shape
и ShapeFactory
и перечисление ShapeType
.«Сервер» предоставляет конкретный экземпляр ShapeFactoryImpl
.