dimanche 5 avril 2015

How to avoid 'instanceof' when implementing factory design pattern?

I am attempting to implement my first Factory Design Pattern, and I'm not sure how to avoid using instanceof when adding the factory-made objects to lists. This is what I'm trying to do:



for (ABluePrint bp : bluePrints) {
AVehicle v = AVehicleFactory.buildVehicle(bp);
allVehicles.add(v);

// Can I accomplish this without using 'instanceof'?
if (v instanceof ACar) {
cars.add((ACar) v);
} else if (v instanceof ABoat) {
boats.add((ABoat) v);
} else if (v instanceof APlane) {
planes.add((APlane) v);
}
}


From what I've read on SO, using 'instanceof' is a code smell. Is there a better way to check the type of vehicle that was created by the factory without using 'instanceof'?


I welcome any feedback/suggestions on my implementation as I'm not even sure if I'm going about this the right way.


Full example below:



import java.util.ArrayList;

class VehicleManager {

public static void main(String[] args) {

ArrayList<ABluePrint> bluePrints = new ArrayList<ABluePrint>();
ArrayList<AVehicle> allVehicles = new ArrayList<AVehicle>();
ArrayList<ACar> cars = new ArrayList<ACar>();
ArrayList<ABoat> boats = new ArrayList<ABoat>();
ArrayList<APlane> planes = new ArrayList<APlane>();

/*
* In my application I have to access the blueprints through an API
* b/c they have already been created and stored in a data file.
* I'm creating them here just for example.
*/
ABluePrint bp0 = new ABluePrint(0);
ABluePrint bp1 = new ABluePrint(1);
ABluePrint bp2 = new ABluePrint(2);
bluePrints.add(bp0);
bluePrints.add(bp1);
bluePrints.add(bp2);

for (ABluePrint bp : bluePrints) {
AVehicle v = AVehicleFactory.buildVehicle(bp);
allVehicles.add(v);

// Can I accomplish this without using 'instanceof'?
if (v instanceof ACar) {
cars.add((ACar) v);
} else if (v instanceof ABoat) {
boats.add((ABoat) v);
} else if (v instanceof APlane) {
planes.add((APlane) v);
}
}

System.out.println("All Vehicles:");
for (AVehicle v : allVehicles) {
System.out.println("Vehicle: " + v + ", maxSpeed: " + v.maxSpeed);
}

System.out.println("Cars:");
for (ACar c : cars) {
System.out.println("Car: " + c + ", numCylinders: " + c.numCylinders);
}

System.out.println("Boats:");
for (ABoat b : boats) {
System.out.println("Boat: " + b + ", numRudders: " + b.numRudders);
}

System.out.println("Planes:");
for (APlane p : planes) {
System.out.println("Plane: " + p + ", numPropellers: " + p.numPropellers);
}
}
}

class AVehicle {

double maxSpeed;

AVehicle(double maxSpeed) {
this.maxSpeed = maxSpeed;
}
}

class ACar extends AVehicle {

int numCylinders;

ACar(double maxSpeed, int numCylinders) {
super(maxSpeed);
this.numCylinders = numCylinders;
}
}

class ABoat extends AVehicle {

int numRudders;

ABoat(double maxSpeed, int numRudders) {
super(maxSpeed);
this.numRudders = numRudders;
}
}

class APlane extends AVehicle {

int numPropellers;

APlane(double maxSpeed, int numPropellers) {
super(maxSpeed);
this.numPropellers = numPropellers;
}
}

class AVehicleFactory {

public static AVehicle buildVehicle(ABluePrint blueprint) {

switch (blueprint.type) {

case 0:
return new ACar(100.0, 4);

case 1:
return new ABoat(65.0, 1);

case 2:
return new APlane(600.0, 2);

default:
return new AVehicle(0.0);
}
}
}

class ABluePrint {

int type; // 0 = car; // 1 = boat; // 2 = plane;

ABluePrint(int type) {
this.type = type;
}
}

Aucun commentaire:

Enregistrer un commentaire