Java 11 Cookbook
上QQ阅读APP看书,第一时间看更新

How it works...

We have already seen one possible implementation of the SpeedModel interface. Here is another way to do it by aggregating the object of the SpeedModel type inside the FactorySpeedModel class: 

public class FactorySpeedModel {
public static SpeedModel generateSpeedModel(
Properties drivingConditions){
//if drivingConditions includes "roadCondition"="Wet"
return new SpeedModelWet(...);
//if drivingConditions includes "roadCondition"="Dry"
return new SpeedModelDry(...);
}
private class SpeedModelWet implements SpeedModel{
public double getSpeedMph(double timeSec, int weightPounds,
int horsePower){
//method code goes here
}
}
private class SpeedModelDry implements SpeedModel{
public double getSpeedMph(double timeSec, int weightPounds,
int horsePower){
//method code goes here
}
}
}

We put comments as pseudocode, and the ... symbol instead of the actual code, for brevity. 

As you can see, the factory class may hide many different private classes, each containing a specialized model for particular driving conditions. Each model produces a different result.

An implementation of the FactoryVehicle class may look like this:

public class FactoryVehicle {
public static Car buildCar(int passengersCount,
int weightPounds, int horsePower){
return new CarImpl(passengersCount, weightPounds,horsePower);
}
public static Truck buildTruck(int payloadPounds,
int weightPounds, int horsePower){
return new TruckImpl(payloadPounds, weightPounds,horsePower);
}
}

The CarImpl private nested class may look as follows inside the  FactoryVehicle class:

  private static class CarImpl extends VehicleImpl implements Car {
private int passengersCount;
private CarImpl(int passengersCount, int weightPounds,
int horsePower){
super(weightPounds + passengersCount * 250, horsePower);
this.passengersCount = passengersCount;
}
public int getPassengersCount() {
return this.passengersCount;
}
}

Similarly, the TruckImpl class can be a private nested class of the FactoryImpl class:

  private static class TruckImpl extends VehicleImpl implements Truck {
private int payloadPounds;
private TruckImpl(int payloadPounds, int weightPounds,
int horsePower){
super(weightPounds+payloadPounds, horsePower);
this.payloadPounds = payloadPounds;
}
public int getPayloadPounds(){ return payloadPounds; }
}

We can place the VehicleImpl class as a private inner class of the FactoryVehicle class too, so the CarImpl and TruckImpl classes can access it, but not any other class outside of FactoryVehicle:

  private static abstract class VehicleImpl implements Vehicle {
private SpeedModel speedModel;
private int weightPounds, horsePower;
private VehicleImpl(int weightPounds, int horsePower){
this.weightPounds = weightPounds;
this.horsePower = horsePower;
}
public void setSpeedModel(SpeedModel speedModel){
this.speedModel = speedModel;
}
public double getSpeedMph(double timeSec){
return this.speedModel.getSpeedMph(timeSec, weightPounds,
horsePower);
}
}

As you can see, an interface describes how to invoke object behavior, while factories can generate different implementations for different requests without changing the code of the client application.