Abstract Factory Pattern in TypeScript — ✨ Creational Design Pattern #2

365kim
4 min readApr 23, 2023

--

Photo by ROCCO STOPPOLONI on Unsplash

🙋🏻‍♀️ What is the Abstract Factory Pattern?

The Abstract Factory Pattern is a design approach that provides an interface for creating families of related objects without specifying their concrete classes.

The idea behind the Abstract Factory Pattern is to encapsulate a group of related objects that can be created in various ways, depending on the needs of the application. This allows the client code to remain unaware of the specific types of objects being created, and to work with them in a generic way.

The pattern defines an abstract factory interface that declares a set of methods for creating the various objects in the family. Each concrete factory that implements the abstract factory interface is responsible for creating a specific set of related objects.

How is it different from Factory Pattern?

We covered Factory Pattern in the last story(#1).

The main difference between these two patterns is the scope of the objects being created. The Factory Pattern(#1) creates objects of a single type, while the Abstract Factory Pattern creates families of related objects.

The Factory Pattern is used to create objects of a single type, and it provides a way to create objects without specifying the exact class of object that will be created. The factory method takes some input, and based on that input, it creates an object of the appropriate type. This allows for loose coupling between the client code and the objects being created.

On the other hand, the Abstract Factory Pattern is used to create families of related objects, and it provides an interface for creating those objects without specifying their concrete classes. This makes sure that the client code and the objects created remain loosely coupled.

✨ Simple TypeScript Example

Imagine that we are using two separate design systems called ‘Blue’ and ‘Red’ to meet different needs, and you are creating a sample user interface application to briefly test each design system.

+--------------------+--------------------+--------------------+
| Variant \ Family | Blue | Red |
+--------------------+--------------------+--------------------+
| Token | Blue Token | Red Token |
| Button | Blue Button | Red Button |
| Dialog | Blue Dialog | Red Dialog |
| Form | Blue Form | Red Form |
| ... | Blue ... | Red ... |
+--------------------+--------------------+--------------------+

Here is an example code of the Abstract Factory pattern in TypeScript:

// Abstract Factory Interface

interface DesignSystemFactory {
createToken(): Token;
createButton(): Button;
createDialog(): Dialog;
createForm(): Form;
// ...
}
class BlueDesignSystemFactory extends DesignSystemFactory {
createToken(): Token {
return new BlueToken();
}

createButton(): Button {
return new BlueButton();
}

createDialog(): Dialog {
return new BlueDialog();
}

createForm(): Form {
return new BlueForm();
}

// ...
}

class RedDesignSystemFactory extends DesignSystemFactory {
createToken(): Token {
return new RedToken();
}

createButton(): Button {
return new RedButton();
}

createDialog(): Dialog {
return new RedDialog();
}

createForm(): Form {
return new RedForm();
}

// ...
}

The two concrete factories Blue...Factory and Red...Factory create different families of related objects.

In the client code:

// generic render function

function render(factory: DesignSystemFactory) {
const token = factory.createToken(); // don't know if it's blue of red
const Button = factory.createButton();
const Form = factory.createForm();
const Dialog = factory.createDialog();

return (
<div style={{ backgroundColor: token.color.primary }}>
<Button />
<Form />
<Dialog />
</div>
)
}

// Using Blue...
render(new BlueDesignSystemFactory());

// Using Red...
render(new RedDesignSystemFactory());

Finally, the render function is used to create the objects based on the type of factory passed to it.

🧑🏻‍💻 Use it or Avoid it

When to use it

The Abstract Factory Pattern is beneficial when an application has to generate multiple sets of interrelated objects, which are designed to work together and you want to enforce these objects to be used in a consistent way.

This is especially useful when you need to change the implementation of a family of objects at runtime without impacting the client code.

When to avoid it

If it’s not necessary to modify the implementation of objects during runtime, it may not be required to create an abstract factory interface, and instead, a concrete factory can be used directly.

If there are a number of objects to create but they are actually not related families of objects, they don’t need to be created together. Or, if you only need to create a single type of object and its creation requirements are not complex, consider the Factory Pattern instead.

In short, the Abstract Factory Pattern promotes loose coupling between the client code and the objects being created, allowing for easy modification of the object families at runtime.

--

--

365kim
365kim

Written by 365kim

Web Front-End Developer who believes Every Day Counts!

No responses yet