JavaScript Design Pattern - Factory Pattern
✅ Common Pattern of the Recurring Problem
Sometimes creating an object involves much more complex logic than the default constructor can give, such as complex configuration, object caching, sharing or re-using objects,
✅ Solution
Factory Pattern
In a factory pattern, a function creates a new object not with new
keyword, but provides a creational constructor, a generic interface where we can pass the type of object one wishes to create as an argument. Informed of the object type, the factory creates and returns the object for us.
Factory pattern
🟢 gives more control over the object creation process; configuration, object caching(🔗 Singleton Pattern), sharing objects, etc.
🟢 eliminates code repetition and creates objects with the same properties and methods.
🟢 is type-safe. you don’t have to worry about typos or accidentally creating objects of different interfaces.
❌ might introduce unnecessary complexity and overhead. Factory pattern is an expensive design decision for simply creating objects with a similar interface. Most of the time, a constructor function and new
operator will suffice. In Learning JavaScript Design Patterns, Addy Osmani says, "unless providing an interface for object creation is a design goal for the library or framework [you] are writing, I would suggest sticking to explicit constructors to avoid the unnecessary overhead."
Consider the following code that implemented a factory pattern without using a prototype chain:
Even though jessica
and john
are both instances of UndergraduateStudent
and thus have the same study
method, the equality of jessica.study === john.greet
resolves to false
. This is because the above code did not take advantage of the prototypal inheritance and creating new study
methods over and over, instead of having them reference to prototype
object(🔗 JavaScript Prototype - Prototype Chain).
Abstract Factory
Abstract Factory encapsulates a group of individual factories by a common theme; in the above example, UndergraduateStudent
and Student
. By doing so, it segregates abstract factory, whose concern is to define the types of objects(UndergraduateStudent
, Student
), and concrete factories, which are in charge of implementing details of corresponding objects.
In the above code, I've refactored the existing example using an abstract factory. The existing createStudent()
method received information of different abstraction levels. The type
of students is high-level information and student information such as name
, major
, are low-level implementation detail Now, StudentFactory
has separate APIs that are addType
and create
. They are respectively in charge of student type
and the information required to create an object of the corresponding type. Now, the abstraction level of a single function is consistent.
✅ Language Integration
In JavaScript, any function that returns an object without using the new
keyword serves as a factory function.
References
Learning JavaScript Design Patterns, Osmani, Addy. O'Reilly
Hallie, Lydia. (2022, August 18). A Tour of JavaScript & React Patterns [video file]. Retrieved from https://frontendmasters.com/courses/tour-js-patterns/