Factory Pattern using Factory Method – Part 2

Continuing on the example of ToyotaCarFactory from our last post Factory Pattern – Part 1, the main aim of the ToyotaCarFactory is to fulfill an order for a ToyotaCar. There are multiple models of Toyota and the factory should manufacture them all.

Our Creator is the CarFactory, having the createCar() factory method which would hold the object instantiation part. ToyotaCarFactory is our concrete creator class which would be responsible for creating the different ToyotaCar objects by providing an implementation of createCar() method. 

As we can see below in the CarFactory code, createCar is our factory method, it is abstract and so will get implemented in subclasses.

public abstract class CarFactory {

     public ToyotaCar orderCar(String model) {
            
            ToyotaCar car;
            car = createCar(model);
            car.assembleParts();
            car.polish();

            return car;
      }
      protected abstract ToyotaCar createCar(String model);
}

CaliforniaToyotaCarFactory and WashingtonToyotaCarFactory are our two factories in California and Washington respectively. CaliforniaToyotaCarFactory produces ToyotaCar objects of type Sienna, Highlander and Prius. WashingtonToyotaCarFactory produces ToyotaCar objects of type Sienna, Highlander, Tacoma. Now if Toyota decides to open another factory in Texas, they will just need to implement TexasToyotaCarFactory and have the concrete objects of the models that that factory will produce. See, how easy it is to add new factories without modifying the already written code. 

public class CaliforniaToyotaCarFactory extends CarFactory {
     ToyotaCar createCar(String model) {
        if(model.equals("sienna") {
            return new Sienna();
        } else if(model.equals("highlander") {
            return new HighLander();
        } else if(model.equals("prius") {
            return new Prius();
        else {
            return null;
        }
    } 
}

public class WashingtonToyotaCarFactory extends CarFactory {
     ToyotaCar createCar(String model) {
        if(model.equals("sienna") {
            return new Sienna();
        } else if(model.equals("highlander") {
            return new HighLander();
        } else if(model.equals("tacoma") {
            return new Tacoma();
        else {
            return null;
        }
    } 
}

As we can see, the concrete classes which extend out CarFactory interface are actually creating new ToyotaCar objects, ie, subclasses are deciding which objects to initialize.

Let’s see how our ToyotaCar and it’s subclasses would look like. 

public abstract class ToyotaCar {
       String modelName;
       String engine;
       String wheels;
       String seats;

       void assembleParts() {
            System.out.println("Assembling "+modelName+" car";
       }

       void polish() {
            System.out.println("Polishing "+modelName+" car";
       }
}
public class Sienna extends ToyotaCar {
        
       public Sienna() {
           modelName = "Sienna";
           engine = "XXX";
           wheels = "four";
           seats = "leather";
      }
}

public class Highlander extends ToyotaCar {
        
       public Highlander() {
           modelName = "Highlander";
           engine = "XXX";
           wheels = "four";
           seats = "leather";
      }
}

Let’s group them all together. To order a Sienna from Califonia factory of Toyota, we will need to initialize the CaliforniaToyotaCarFactory and then call the orderCar method on it with “sienna” as parameter. This would in turn call the createCar implementation of CaliforniaToyotaCarFactory, which will initialize the Sienna object. 

public class ToyotaTestDrive {

public static void main(String[] args) {
      CarFactory calToyotaCarFactory = new CaliforniaToyotaCarFactory();
      CarFactory washToyotaCarFactory = new WashingtonToyotaCarFactory();

      ToyotaCar car = calToyotaCarFactory.orderCar("sienna");
System.out.println("Ordered Car "+car.getName());

      ToyotaCar car = washToyotaCarFactory.orderCar("tacoma");
System.out.println("Ordered Car "+car.getName());

In next post we will see, how Abstract Factory Pattern work.


One response to “Factory Pattern using Factory Method – Part 2”