DEV Community

Cover image for Factory Design Pattern - Creational Design Pattern
AryaGG
AryaGG

Posted on • Edited on

Factory Design Pattern - Creational Design Pattern

  • Creational design pattern - ways to create objects.

  • These design patterns are used when a decision must be made at the time of instantiation of a class (i.e. creating an object of a class).

  • It provides a great deal of flexibility in what is created , who creates it, and how it is created

Image description

Factory Method Design Pattern

  • Factory design pattern defines an interface for creation objects, but allow sub classes to alter the type of objects that will be created.
  • The Factory Design Pattern allows you to delegate the responsibility of object creation to a factory class, instead of directly instantiating the class yourself in the client code.

Real-World Example:
Imagine you have are running a factory that produces different vehicles: cars, bikes & trucks. The process of manufacturing each type of vehicle is different. But the person ordering vehicle doesn't know the details how each vehicle is produced-they just need their vehicle.
Instead of exposing the complex logic of vehicle creation to the client, we use a factory method to handle the creation process for us. The client only interacts with a single interface, and the factory decides which specific type of vehicle to create.
Instead of directly creating concrete classes (like Car(),Bike()..) the factory method pattern provides an interface or abstract class with factory method that is implemented by concrete classes.

// Abstract Product (Vehicle)
class Vehicle {
  manufacture() {
    throw new Error("This method should be overridden by concrete products");
  }
}

// Concrete Products
class Car extends Vehicle {
  manufacture() {
    return "Manufacturing a Car.";
  }
}

class Bike extends Vehicle {
  manufacture() {
    return "Manufacturing a Bike.";
  }
}

class Truck extends Vehicle {
  manufacture() {
    return "Manufacturing a Truck.";
  }
}

// Abstract Factory
class VehicleFactory {
  createVehicle() {
    throw new Error("This method should be implemented by concrete factories");
  }
}

// Concrete Factories
class CarFactory extends VehicleFactory {
  createVehicle() {
    return new Car();  // Create a Car
  }
}

class BikeFactory extends VehicleFactory {
  createVehicle() {
    return new Bike();  // Create a Bike
  }
}

class TruckFactory extends VehicleFactory {
  createVehicle() {
    return new Truck();  // Create a Truck
  }
}

// Client code
function getVehicle(factory) {
  const vehicle = factory.createVehicle();  // Uses the factory method
  console.log(vehicle.manufacture());
}

// Using the factory to get different vehicles
const carFactory = new CarFactory();
const bikeFactory = new BikeFactory();
const truckFactory = new TruckFactory();

getVehicle(carFactory);   // Output: Manufacturing a Car.
getVehicle(bikeFactory);  // Output: Manufacturing a Bike.
getVehicle(truckFactory); // Output: Manufacturing a Truck.

Enter fullscreen mode Exit fullscreen mode

If you want to add new vehicle type eg: "Bus" you can add without changing the client code, making system more flexible and maintainable.

Factory : An abstract class or interface creates objects without specifying the exact class. Subclasses decide which class to instantiate, making the code flexible and easier to maintain.
Abstract Class: Cannot be instantiated directly. It provides a template with both abstract (no implementation) and concrete (with implementation) methods.
Concrete class : It is a class in object-oriented programming that can be instantiated, meaning you can create objects from it. Unlike abstract classes, which may have unimplemented methods, a concrete class provides full implementations for all its methods. This makes it a complete blueprint that can be used to create instances.

Use Case

// Step 1: Define the DatabaseConnection interface
public interface DatabaseConnection {
    void connect();
}

// Step 2: Implement concrete classes for different databases
public class MySQLConnection implements DatabaseConnection {
    @Override
    public void connect() {
        System.out.println("Connecting to MySQL database...");
    }
}

public class PostgreSQLConnection implements DatabaseConnection {
    @Override
    public void connect() {
        System.out.println("Connecting to PostgreSQL database...");
    }
}

public class SQLiteConnection implements DatabaseConnection {
    @Override
    public void connect() {
        System.out.println("Connecting to SQLite database...");
    }
}

// Step 3: Create an abstract factory class
public abstract class DatabaseConnectionFactory {
    public abstract DatabaseConnection createConnection();
}

// Step 4: Implement factory classes for each database type
public class MySQLConnectionFactory extends DatabaseConnectionFactory {
    @Override
    public DatabaseConnection createConnection() {
        return new MySQLConnection();
    }
}

public class PostgreSQLConnectionFactory extends DatabaseConnectionFactory {
    @Override
    public DatabaseConnection createConnection() {
        return new PostgreSQLConnection();
    }
}

public class SQLiteConnectionFactory extends DatabaseConnectionFactory {
    @Override
    public DatabaseConnection createConnection() {
        return new SQLiteConnection();
    }
}

// Step 5: Use the factory to create database connections
public class Main {
    public static void main(String[] args) {
        DatabaseConnectionFactory factory;

        // Example: Creating a MySQL connection
        factory = new MySQLConnectionFactory();
        DatabaseConnection mySQLConnection = factory.createConnection();
        mySQLConnection.connect();

        // Example: Creating a PostgreSQL connection
        factory = new PostgreSQLConnectionFactory();
        DatabaseConnection postgreSQLConnection = factory.createConnection();
        postgreSQLConnection.connect();

        // Example: Creating a SQLite connection
        factory = new SQLiteConnectionFactory();
        DatabaseConnection sqliteConnection = factory.createConnection();
        sqliteConnection.connect();
    }
}
Enter fullscreen mode Exit fullscreen mode

In this example:
DatabaseConnection is the interface for different types of database connections.
MySQLConnection, PostgreSQLConnection, and SQLiteConnection are concrete implementations of the DatabaseConnection interface.
DatabaseConnectionFactory is an abstract factory class with a method createConnection().
MySQLConnectionFactory, PostgreSQLConnectionFactory, and SQLiteConnectionFactory are concrete factory classes that create specific database connections.

This pattern allows you to create database connections without specifying the exact class, making the code more flexible and easier to maintain.

Image description

Top comments (0)