Abstract Factory Pattern

In the last two posts on Factory Pattern using Factory method – part 1 and part 2, we went through how factory method works, using the toyota car factory example. Let’s continue to build on that example and understand the Abstract Factory Pattern. 

Using the factory method, we implemented our interfaces CarFactory and ToyotaCar and their concrete implementations for Toyota. But the toyota leaders found out that their factories in California and Washington are not using the genuine toyota parts while assembling Toyota cars, thereby degrading quality of the cars. And so toyota has decided to create a factory for genuine toyota parts that produces these parts and sends them to the car factories. 

Let’s call the parts factory ToyotaPartsFactory. CaliforniaToyotaPartsFactory and WashingtonToyotaPartsFactory will now supply these parts to the CaliforniaToyotaCarFactory and WashingtonToyotaCarFactory respectively

public interface ToyotaPartsFactory {

       public Engine createEngine();
       public Wheels wheels();
       public Seats seats();
}
Abstract Factory Pattern using Toyota Parts Factory example
public class CaliforniaToyotaPartsFactory implements ToyotaPartsFactory {
 
      public Engine createEngine() {
            return V8Engine();
      }

      public Wheels createWheels() {
            return AlloyWheels();
      }

      public Seats createSeats() {
             return LeatherSeats()l
      }
}

Our new ToyotaCar object would now have an abstract method called assembleParts. This would be implemented by the subclasses to use the correct parts while assembling the car. In our concrete CarFactories, we will now be passing the respective ToyotaPartFactories. As shown below, in the CaliforniaToyotaPartsFactory we are passing the CaliforniaToyotaPartsFactory.

public abstract class ToyotaCar {
       String modelName;
       Engine engine;
       Wheels wheels;
       Seats seats;

       abstract void assembleParts();

       void polish() {
            System.out.println("Polishing "+modelName+" car";
       }
}

public class Sienna extends ToyotaCar {
        ToyotaPartsFactory toyotaPartsFactory;

        public Sienna(ToyotaPartsFactory toyotaPartsFactory) {
             this.toyotaPartsFactory = toyotaPartsFactory;
         }

         void assembleParts() {
              System.out.println("Assembling "+modelName+" car";
              engine = toyotaPartsFactory.createEngine();
              wheels = toyotaPartsFactory.createWheels();
              seats = toyotaPartsFactory.createSeats();
         }
}

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

We now have the power to create a family of different part objects. That’s what an Abstract Factory does. It gives an interface for creating a factory of products. The second advantage is decoupling. Our code for creating products (ToyotaCar) is decoupled from the code for creating the other line of product families. It opens up the architecture for creating different types of factories needed, with each decoupled from others.

Abstract Factory Pattern

Thanks for stopping by! Hope this gives you a perspective on Abstract Factory pattern. Post comments to start a discussion. See you in the next post.