Pattern - Abstract Factory
Published: 2023-01-14 20:11:46

![Abstract Factory](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2xxyfhp18yq16xwob61e.jpg)

The _Abstract Factory_ design pattern was formalized and described as one of the 23 GoF (Gang of Four) patterns in the book "Design Patterns: Elements of Reusable Object-Oriented Software" written by Erich Gamma, Richard Helm, Ralph Johnson, and John Vlissides in 1994.


The _Abstract Factory_ pattern is a software design pattern that allows you to create families of related or dependent objects without specifying their concrete classes. It's similar to the Factory Method pattern, but it's one level up, that is, instead of creating just one object, the _Abstract Factory_ pattern creates a series of related objects.

The _Abstract Factory_ has an interface to create each type of object you want, but it lets the subclasses decide which concrete classes to use. This allows you to change the family of created objects without affecting the classes that use those objects.

An example use of _Abstract Factory_ would be creating themes for an application, where there are many different themes with buttons, dialogs and other UI elements. Each theme is a family of related objects, and _Abstract Factory_ would allow you to create a new family of objects for a new theme without affecting the classes that use those objects.

The _Abstract Factory_ is slightly more complex than the [Factory Method](https://dev.to/higordiego/padrao-factory-method-1k53) pattern, and is used in situations where there are multiple families of related objects or dependents. It is useful for working with complex systems that can be broken down into smaller, easier-to-understand systems.

One of the main advantages of using the _Abstract Factory_ pattern include:

- Abstraction of object creation: As mentioned before, the _Abstract Factory_ allows you to create objects of different types without needing to know the concrete class that will be used to create them. This allows you to change the family of created objects without affecting the classes that use those objects.
- Scalability and flexibility: The _Abstract Factory_ pattern helps keep code scalable and flexible. New object families can be added easily without affecting existing code.
- Isolation of design logic: _Abstract Factory_ allows you to isolate the design logic of objects from system logic, making them easier to modify and maintain.
- Code reuse: The concrete classes created by _Abstract Factory_ can be reused elsewhere in the system.


Below is an example of the _Abstract Factory_ pattern for creating different types of database connections in a software with nodejs.



```js

class Connection {
    constructor(type) {
        this.type = type
    }
    connect() {
        // lógica para conectar
    }
    query() {
        // lógica para fazer consultas
    }
    close() {
        // lógica para fechar a conexão
    }
}

class MySQLConnection extends Connection {
    constructor() {
        super('mysql')
    }
}

class MongoDBConnection extends Connection {
    constructor() {
        super('mongodb')
    }
}

class ConnectionFactory {
    createConnection(type) {
        switch (type) {
            case 'mysql':
                return new MySQLConnection()
            case 'mongodb':
                return new MongoDBConnection()
            default:
                throw new Error('Unknown connection type')
        }
    }
}

const factory = new ConnectionFactory()
const mysqlConnection = factory.createConnection('mysql')
mysqlConnection.connect()
mysqlConnection.query('SELECT * FROM users')
mysqlConnection.close()

const mongodbConnection = factory.createConnection('mongodb')
mongodbConnection.connect()
mongodbConnection.query({})
mongodbConnection.close()

```

The _"Connection"_ class is an abstract class that defines the interface for database connections. It has methods for connecting, querying, and closing the connection.

The _"MySQLConnection"_ and _"MongoDBConnection"_ classes are the concrete classes that extend the _"Connection"_ class and implement the specific logic for each type of connection.
 
They also define the connection type by calling super in the constructor.

The _"ConnectionFactory"_ class is the _Abstract Factory_ itself, it has the "createConnection" method which is responsible for creating the connection instances according to the passed type.

At the end of the code, an instance of the _"ConnectionFactory"_ class is created and the createConnection method is called, passing 'mysql' or 'mongodb' and thus a specific connection instance is created for each type. After that, the connect, query and close methods are called for the created instances.

_Simple, right?_

Imagine another scenario in which your team manager informed you that there is a need to build a dashboard whose purpose is to list users and their requests through an internal API.

To solve the following problem follow the example below:


```js
class API {
    constructor(baseURL) {
        this.baseURL = baseURL;
    }
    
    fetch(endpoint) {
        return fetch(`${this.baseURL}/${endpoint}`)
                    .then(response => response.json())
    }
}

class UsersAPI extends API {
    constructor() {
        super('https://my-app.com/api/users');
    }
    getUsers() {
        return this.fetch('users');
    }
}

class OrdersAPI extends API {
    constructor() {
        super('https://my-app.com/api/orders');
    }
    getOrders() {
        return this.fetch('orders');
    }
}

class APIFactory {
    createAPI(type) {
        switch (type) {
            case 'users':
                return new UsersAPI();
            case 'orders':
                return new OrdersAPI();
            default:
            throw new Error('Unknown API type');
        }
    }
}

const factory = new APIFactory();
const usersAPI = factory.createAPI('users');
usersAPI.getUsers().then(console.log);

const ordersAPI = factory.createAPI('orders');
ordersAPI.getOrders().then(console.log);

```

The _API_ class is an abstract class that defines the interface for the APIs. It has a constructor that receives the API's base URL and a fetch method that makes a GET request to the API, passing the specific endpoint.

The _UsersAPI_ and _OrdersAPI_ classes are concrete classes that extend the API class and implement logic specific to each API type. They also define the base URL of the API through the call to super() in the constructor.

The _APIFactory_ class is the _Abstract Factory_ itself, it has the _createAPI_ method which is responsible for creating API instances according to the passed type.

At the end of the code, an instance of the _APIFactory_ class is created and the _createAPI_ method is called, passing 'users' or 'orders' and thus a specific API instance is created for each type. After that, the _getUsers()_ or _getOrders()_ method are called for the created instances, and these methods already return a Promise that handles the API return.

You can use the _Abstract Factory_ pattern when:

- You have several families of related or dependent objects, and you need to create objects from these families without specifying their concrete classes;
- You want to provide a simple way to create objects, but you want to hide your application's creation logic;
- You want to provide a way to change the families of created objects without affecting the classes that use those objects;
- When there are multiple combinations of object types and structures, and these combinations need to be created in an organized way;
- If you have a complex system that can be broken down into smaller, easier-to-understand systems, and you want to encapsulate the logic behind creating these smaller systems;
- If you are working with object-oriented systems.


**Conclusion**

This pattern helps keep code scalable and flexible, as new object families can be added easily without affecting existing code. It also allows the object creation logic to be isolated from the system logic, making it easier to modify and maintain.


Hope this helps, until next time.