Abstract Factory Pattern

Abstract Factory Pattern says that just define an interface or abstract class for creating families of related (or dependent) objects but without specifying their concrete sub-classes.

Abstract Factory pattern is almost similar to Factory Pattern is considered as another layer of abstraction over factory pattern. Abstract Factory patterns work around a super-factory which creates other factories.

When to use Abstract Factory Pattern :

  • there are number of products fall into families
  • the families of products need to stay together, but only one subset of families can be used at a particular time
  • the internal implementation is hidden and needs to expose via an interface
  • the client does not need internal implementations and details of object creations
  • the system needs more modularity and abstraction to separate the functionalities Standard Class Diagram

// Java Program to demonstrate the
// working of Abstract Factory Pattern

enum class CarType {
    MICRO, MINI, LUXURY
}

abstract class Car(model: CarType, location: Location) {

    var model: CarType? = null
    var location: Location? = null

    init {
        this.model = model
        this.location = location
    }

    abstract fun construct()

    override fun toString(): String {
        return "CarModel - $model located in $location"
    }
}

class LuxuryCar(location: Location) : Car(CarType.LUXURY, location) {
    init {
        construct()
    }

     override fun construct() {
        println("Connecting to luxury car")
    }
}

class MicroCar(location: Location) : Car(CarType.MICRO, location) {
    init {
        construct()
    }

    override fun construct() {
        println("Connecting to Micro Car ")
    }
}

class MiniCar(location: Location) : Car(CarType.MINI, location) {
    init {
        construct()
    }

    override fun construct() {
        println("Connecting to Mini car")
    }
}

enum class Location {
    DEFAULT, USA, INDIA
}

class INDIACarFactory {
    fun buildCar(model: CarType): Car? {
        var car: Car? = null
        when (model) {
            CarType.MICRO -> car = MicroCar(Location.INDIA)

            CarType.MINI -> car = MiniCar(Location.INDIA)

            CarType.LUXURY -> car = LuxuryCar(Location.INDIA)

            else -> {
            }
        }
        return car
    }
}

fun buildCar(model: CarType): Car? {
    var car: Car? = null
    when (model) {
        CarType.MICRO -> car = MicroCar(Location.DEFAULT)

        CarType.MINI -> car = MiniCar(Location.DEFAULT)

        CarType.LUXURY -> car = LuxuryCar(Location.DEFAULT)

        else -> {
        }
    }
    return car
}



internal object USACarFactory {
    fun buildCar(model: CarType): Car? {
        var car: Car? = null
        when (model) {
            CarType.MICRO -> car = MicroCar(Location.USA)

            CarType.MINI -> car = MiniCar(Location.USA)

            CarType.LUXURY -> car = LuxuryCar(Location.USA)

            else -> {
            }
        }
        return car
    }
}


class CarFactory {
    fun buildCar(type: CarType): Car? {
        var car: Car? = null
        // We can add any GPS Function here which
        // read location property somewhere from configuration
        // and use location specific car factory
        // Currently I'm just using INDIA as Location
        val location = Location.INDIA

        when (location) {
            Location.USA -> car = USACarFactory.buildCar(type)

            Location.INDIA -> car = INDIACarFactory().buildCar(type)

            else -> car = buildCar(type)
        }

        return car

    }
}

fun main(args: Array<String>) {
    println(CarFactory().buildCar(CarType.MICRO))
    println(CarFactory().buildCar(CarType.MINI))
    println(CarFactory().buildCar(CarType.LUXURY))
}			

Output of the Abstract factory pattern in kotlin


Connecting to Micro Car 
CarModel - MICRO located in INDIA
Connecting to Mini car
CarModel - MINI located in INDIA
Connecting to luxury car
CarModel - LUXURY located in INDIA			

Advantages of Abstract Factory Pattern :

  • Enabled error-free management of families of related products
  • Concrete factories work independently of each other, enabling easy product family exchange and handling at run-time
  • Improves consistency among related products
  • Many objects can be added or changed dynamically during the run-time
  • Divides the responsibilities among multiple concrete factory classes
  • Can add more products to families and concrete factories will take care about those product creations
  • Enforce encapsulation and modularization through concrete factories and abstract interfaces
  • The client program is independent of the internal object construction mechanism
  • Abstract factory avoids long conditional logic as in factory pattern

 
Join My Facebook Group
Join Group
 

About Author

This article is written by Pavan, who is serving notice period in an MNC, Bangalore. He thought, let the articles speak rather than his image. He is also the same person who created the reporter for Protractor Jasmine

Share this Article Facebook
Comment / Suggestion Section
Point our Mistakes and Post Your Suggestions