2016-03-21 16 views
3

Ich habe folgendes Beispiel in Java:die richtige Methode für ein Objekt aufrufen, wenn das Objekt eine Instanz einer Basisklasse ist

public abstract class Vehicle { 
    private final String name; 
    private final String make; 

    public Vehicle(final String name, final String make) { 
     this.make = make; 
     this.name = name; 
    } 
} 

public final class Car extends Vehicle { 
    public Car(final String name, final String make) { 
     super(name, make); 
    } 
} 

public final class Truck extends Vehicle { 
    final Integer grossVehicleWeight; 

    public Truck(final String name, final String make, final Integer gvw) { 
     super(name, make); 
     this.grossVehicleWeight = gvw; 
} 

sagen, dass ich etwas Arbeit mit einem Fahrzeug tun wollen, und die Arbeit ist nicht abhängig von der Unterklasse des Fahrzeugs. So habe ich eine Methode in einer anderen Klasse wie folgt:

public void doStuff(public final Vehicle vehicle) { 
    //do stuff here 
    //then insert it into my database: 
    insertVehicle(vehicle); 
} 

Allerdings möchte ich in meinem insertVehicle verschiedene Dinge zu tun, so überschreiben ich diese Methode für jede Unterklasse:

public void insertVehicle(Car car) { //do stuff for a car } 

public void insertVehicle(Truck truck) { //do stuff for a truck } 

In meinem doStuff Methode I instanceOf verwenden könnte die Klasse des Fahrzeugs (PKW oder LKW), und dann gegossen, das Fahrzeug in dieser Klasse und rufen die insertVehicle Methode wie folgt zu bestimmen:

public void doStuff(public final Vehicle vehicle) { 
    //do stuff here 
    //then insert it into my database: 
    if (vehicle instanceof Car) { 
     insertVehicle((Car) vehicle); 
    } else { 
     insertVehicle((truck) vehicle); 
    } 
} 

ich habe jedoch r ead, dass instanceof ist nicht der beste Weg, dies zu tun. 1

Wie kann ich das am besten überarbeiten, damit ich instanceof nicht verwenden muss?

+0

Was machen diese insertVehicle-Methoden? Die OO-Methode besteht darin, insertVehicle (oder den spezifischen Teil dieser Methode) zu einer Instanzmethode von Vehicle zu machen, die in jeder Unterklasse außer Kraft gesetzt wird. Oder um das Besuchermuster zu verwenden. Posten Sie Ihren Code für konkretere Hilfe. –

Antwort

3

können Sie das Besuchermuster verwenden:

public interface VehicleVisitor { 
    public void visit(Car car); 
    public void visit(Truck truck); 
} 

public class Car extends Vehicle { 

    @Override 
    public void insert(VehicleVisitor vehicleVisitor) { 
     vehicleVisitor.visit(this); 
    } 
} 

public class Truck extends Vehicle { 
    @Override 
    public void insert(VehicleVisitor vehicleVisitor) { 
     vehicleVisitor.visit(this); 
    } 
} 

public abstract class Vehicle { 
    public abstract void insert(VehicleVisitor vehicleVisitor); 
} 

public class VehicleVisitorImpl implements VehicleVisitor { 

    @Override 
    public void visit(Car car) { 
     System.out.println("insert car"); 
    } 

    @Override 
    public void visit(Truck truck) { 
     System.out.println("insert truck"); 
    } 
} 

public class Main { 

    public static void main(String[] args) { 
     Vehicle vehicle = new Car(); 
     // finally the agnostic call 
     vehicle.insert(new VehicleVisitorImpl()); 
    } 

} 
3

Sie können die abstrakte Funktion innerhalb des Fahrzeugs machen für

public abstract void doStuff() 

Aufruf dieser Funktion von der Instanz des Objekts, das Sie

ändern möchten
ford.doStuff();  //ford is car instance 

und dann können Sie diese Änderung vornehmen.

doStuff() 
{ 
    this.cost += 10; 
} 

Andernfalls können Sie eine Variable für das Fahrzeug hinzufügen, die den Fahrzeugtyp angibt und zurücksenden. Wie:

public void doStuff(public final Vehicle vehicle) { 
     //do stuff here 
     //then insert it into my database: 
     if (vehicle.getType()== 'Car') { 
      insertVehicle((Car) vehicle); 
     } else { 
      insertVehicle((truck) vehicle); 
     } 
    } 

Diese Variable 'vehicleType' wird in der Fahrzeugklasse und wird innerhalb des Konstruktors initialisiert werden:

public final class Car extends Vehicle { 
     public Car(final String name, final String make, final String vehicleType) { 
      super(name, make, type); 
     } 
    } 
0

Eine Möglichkeit ist es, die insertVehicle() Methode abstrakt in Vehicle zu haben. Und dann implementieren Sie sie in den Unterklassen Car und Truck.

Dies verschiebt jedoch die Logik in die POJOs. Vielleicht ist es besser, db-logic von den POJOs zu trennen, d. H. In diesem Fall einfach instanceof verwenden.

public abstract class Vehicle { 
    private final String name; 
    private final String make; 

    public Vehicle(final String name, final String make) { 
     this.make = make; 
     this.name = name; 
    } 

    public abstract void insertVehicle(); 
} 

public final class Car extends Vehicle { 
    public Car(final String name, final String make) { 
     super(name, make); 
    } 

    public void insertVehicle() { 

    } 
} 

public final class Truck extends Vehicle { 
    final Integer grossVehicleWeight; 

    public Truck(final String name, final String make, final Integer gvw) { 
     super(name, make); 
     this.grossVehicleWeight = gvw; 
    } 

    public void insertVehicle() { 

    } 
} 

public void doStuff(Vehicle vehicle) { 
    //do stuff here 
    //then insert it into my database: 
    vehicle.insertVehicle(); 
} 
1

Es hängt davon ab, welche Art von Problem Sie versuchen zu lösen. Wenn es Persistenz ist, stellen Sie sicher, dass Sie nicht JPA neu erfinden. Wenn es sich um eine typspezifische Verarbeitung handelt, können Sie sie wie von @denis vorgeschlagen lösen.Oder wenn Sie Entitäten in POJO-Stil halten möchten, können Sie strategy pattern wie verwenden:

Map<Class<?>, Consumer<Vehicle>> consumers; 
{ 
    consumers.put(Car.class, v -> insertVehicle((Car)v)); 
    consumers.put(Truck.class, v -> insertVehicle((Truck)v)); 
} 
public void doStuff(public final Vehicle vehicle) { 
    //do stuff here 
    consumers 
     .get(vehicle.getClass()) 
     .accept(vehicle); 
} 
0

Wenn Sie nicht wie doStuff() in Car und Truck setzen, könnten Sie haben eine doStuff() Verfahren für jeden von ihnen, und setzen die gemeinsame Vehicle Logik in eine andere Methode.

private void doCommonStuff(final Vehicle vehicle) { 
    //do stuff here 
} 

public void doStuff(final Car car) { 
    doCommonStuff(car); 
    //then insert it into my database: 
    insertVehicle(car); 
} 

public void doStuff(final Truck truck) { 
    doCommonStuff(truck); 
    //then insert it into my database: 
    insertVehicle(truck); 
} 

Wir können jedoch mit Generika besser machen.

public abstract class StuffDoer<T extends Vehicle> { 
    public void doStuff(final T vehicle) { 
    // do stuff here 
    // then insert it into my database: 
    insertVehicle(vehicle); 
    } 

    public abstract void insertVehicle(T vehicle); 
} 

public class CarStuffDoer extends StuffDoer<Car> { 
    public void insertVehicle(Car car) { 
    // whatever 
    } 
} 

public class TruckStuffDoer extends StuffDoer<Truck> { 
    public void insertVehicle(Truck truck) { 
    // whatever else 
    } 
} 
Verwandte Themen