Ваш вопрос имеет смысл, но на самом деле я думаю, что определение или нет базового класса для класса Product действительно зависит от того, каким образом вы хотите реализовать свои компоновщики.
Я думаю, что реализации по умолчанию класса абстрактного компоновщика могут знать о базовом классе для построения Продукта, но на самом деле никаких обязательств.
Например, в цитируемом примере он может просто добавить строку, возвращаемую методом, к строке, которая является состоянием объекта, который нужно построить. В этом случае зачем определять абстрактный класс Product? Нам это не нужно.
Даже в более сложных построенных объектах для любых методов, реализованных в абстрактном классе построителя, вы можете хранить каждую часть объекта для построения в состоянии абстрактного класса построителя и использовать эти части без необходимости какого-либо базового класса для Товарный класс.
Например, вот реализация без базового класса для продукта
Клиент:
Builder builder = new ParadiseWorldBuilder();
World world = director.build(builder);
Режиссер:
World build(){
builder.buildLands(...); // defined in abstract class for example
builder.buildPeople(...);
builder.buildAnimals(...);
return builder.getWorld();
}
Абстрактный класс строителя:
private List<Land> lands = ...;
List<Land> getLands(){return lands;}
void buildLands(){
for(....){
lands.add(...);
}
}
Класс бетоностроителя:
World getWorld(){
return new ParadiseWorld(getLands(), ...); // use the state of the abstract class
}
Теперь, просто чтобы показать вам, что это вопрос выбора, я изменю реализацию примера и буду полагаться на общий базовый класс для класса Product (здесь World
).
Реализация с базовым классом для Продукта
Клиент:
Builder builder = new ParadiseWorldBuilder();
World world = director.build(builder);
Режиссер:
World build(){
builder.buildLands(...); // defined in abstract class for example
builder.buildPeople(...);
builder.buildAnimals(...);
return builder.getWorld();
}
Абстрактный класс строителя:
protected World world = createEmptyWorld(); // abstract method
void buildLands(){
for(....){
world.addLands(...);
}
}
World getWorld(){
return world;
}
Аннотация Класс товара:
public World{
void addLands(...){
// ...
}
}
Класс продукции:
public ParadiseWorld extends World{
//...
}
Класс бетоностроителя:
World createEmptyWorld(){
return new ParadiseWorld();
}
IHMO в этом примере подход без базового класса для продукта намного лучше. Это уменьшает связь между строителями и продуктами. Кроме того, здесь иерархия выглядит поверхностной, и делегирование между создателем и продуктом, который создается для каждой сборочной детали, выглядит накладными расходами и предотвращает неизменность для класса Product (что может быть желательно).