Я делал это в похожих ситуациях.
Вариант А)
Если специализированные операции являются частью той же последовательности, что и базовая операция (например, ConvertibleVehicle необходимо согнуть, чтобы она могла двигаться), просто поместите специализированную операцию в базовую операцию.
class Vehicle {
public abstract void drive();
}
class ConvertibleVehicle {
public void drive() {
this.foldRoof();
.... // drive
}
private void foldRoof() {
....
}
}
Таким образом, эффект от вождения флота будет заключаться в том, что некоторые из них свернут крышу до того, как будут управляться.
for( Vehicle v : vehicleFleet ) {
v.drive();
}
Специализированный метод не предоставляется в открытом интерфейсе объекта, но вызывается при необходимости.
Вариант B)
Если специализированная операция не является частью одной и той же последовательности и должна вызываться при определенных «особых» обстоятельствах, то пусть специализированная версия клиента вызывает эти специализированные операции. Предупреждение, это не так чисто и не является слабой связью, но когда оба объекта (клиент и сервис) создаются одним и тем же «условием» или компоновщиком, в большинстве случаев это нормально.
class Vehicle {
public void drive() {
....
}
}
class ConvertibleVehicle extends Vehicle {
// specialized version may override base operation or may not.
public void drive() {
...
}
public void foldRoof() { // specialized operation
...
}
}
Почти так же, как и в предыдущем примере, только в этом случае foldRoof также является публичным.
Разница в том, что мне нужен специализированный клиент:
// Client ( base handler )
public class FleetHandler {
public void handle( Vehicle [] fleet ) {
for( Vehicle v : fleet ) {
v.drive();
}
}
}
// Specialized client ( sophisticate handler that is )
public class RoofAwareFleetHandler extends FleetHandler {
public void handle( Vehicle [] fleet ) {
for( Vehicle v : fleet ) {
// there are two options.
// either all vehicles are ConvertibleVehicles (risky) then
((ConvertibleVehicles)v).foldRoof();
v.drive();
// Or.. only some of them are ( safer ) .
if( v instenceOf ConvertibleVehicle ) {
((ConvertibleVehicles)v).foldRoof();
}
v.drive();
}
}
}
Это instaceof выглядит там довольно некрасиво, но это может быть подчеркнуто современной виртуальной машиной.
Суть в том, что только специализированный клиент знает и может вызывать специализированные методы. То есть только RoofAwareFleetHandler может вызвать foldRoof () при ** ConvertibleVehicle **
Финальный код не меняется ...
public class Main {
public static void main( String [] args ) {
FleetHandler fleetHandler = .....
Vehicles [] fleet = ....
fleetHandler.handle( fleet );
}
}
Конечно, я всегда проверяю совместимость автопогрузчика и множества транспортных средств (возможно, с использованием abstrac фабрики или производителя)
Надеюсь, это поможет.