Tutorial

JavaScript Object Oriented Patterns: Factory Pattern

Published on January 23, 2019
author

Vijay Prasanna

JavaScript Object Oriented Patterns: Factory Pattern

Organizing code is going to save us from a lot of pain. Using the features of Object Oriented programming, we can employ certain design patterns to achieve better readability, reduce redundancy and create abstractions, if needed. One such pattern is the factory pattern.

The factory pattern is a type of Object Oriented pattern which follows the DRY methodology. As the name suggests, object instances are created by using a factory to make the required object for us.

Let’s have a look at a very simple example of using the factory pattern to assemble an alligator object. To do that we first need to make factories that create the alligator parts for us:

class TailFactory {
  constructor(props) {
    this.tailLength = props.tailLength;
  }
};

class TorsoFactory {
  constructor(props) {
    this.color = props.color;
  }
};

class HeadFactory {
  constructor(props) {
    this.snoutLenth = props.snoutLenth;
  }
};

Now, we create a class that acts as an intermediary between the actual factories classes and the user. Let’s call this the ReptilePartFactory:

class ReptilePartFactory {
  constructor(type, props) {
    if(type === "tail")
      return new TailFactory(props);
    if(type === "torso")
      return new TorsoFactory(props);
    if(type === "head")
      return new HeadFactory(props);
  }
};

Let’s go ahead and assemble the actual alligator now and use the ReptilePartFactory to get the required parts for us:

let alligator = {};
let alligatorProps = {
  tailLength : 2.5, 
  color: "green",
  snoutLenth: 1
};

//gets a tail from the tail factory
alligator.tail  = new ReptilePartFactory("tail", alligatorProps); 

//gets a torso from the torso factory
alligator.torso = new ReptilePartFactory("torso", alligatorProps);

//gets a head from the head factory
alligator.head  = new ReptilePartFactory("head", alligatorProps);

Take at the look the pattern above, it seems like we could use the same ReptilePartFactory to create parts for alligator-like objects. The factories in the background would never have to know about the nature of the final object.

Thus, using the factory pattern gives us certain advantages:

  • Dynamic object creation: It can be used in cases where the type of the object is decided at runtime.
  • Abstraction: The user never really has to access the actual object’s constructor.
  • Reusability/Maintenance: Same factories can be used for similar objects and it allows us to add/remove new object classes easily without changing a lot of code.

Now that we have some understanding of the factory pattern, let’s explore a little bit on writing better factory pattern code.

The example above uses an if-ladder to find out which factory to call based on user input. This is a simple implementation, intuitive and not very open to changes. If we have new parts to add later, then we’d have to disturb the ReptilePartFactory. This is a violation of SOLID principles, which states “Software entities (classes, modules, functions, etc.) should be open for extension, but closed for modification”.

How about we store the factory classes in an object and call the required part factory by using the part we want as the key? First we’d have to register the factories, it’d be as simple as:

let registeredPartFactories = {};
registeredPartFactories['tail'] = class TailFactory{
  ...
};

registeredPartFactories['torso'] = class TorsoFactory {
  ...
};

registeredPartFactories['head'] = class HeadFactory {
  ...
};

And now, the abstract layer can call the factories like this:

class ReptilePartFactory {
  constructor(type, props) {
    return new registeredPartFactories[type](props);
  }
};

This approach is much cleaner and allows to expand our factories without affecting code in the ReptilePartFactory.

In conclusion

There are several other object oriented patterns which also increase readability and quality. So before using the factory pattern, check if there is a real requirement for it. If you’re going to create similar types of objects repeatedly and also need a layer to create new instances using these objects while providing some level of abstraction to the creation logic, then yes - the factory pattern is a good option.

Thanks for learning with the DigitalOcean Community. Check out our offerings for compute, storage, networking, and managed databases.

Learn more about our products

About the authors
Default avatar
Vijay Prasanna

author

While we believe that this content benefits our community, we have not yet thoroughly reviewed it. If you have any suggestions for improvements, please let us know by clicking the “report an issue“ button at the bottom of the tutorial.

Still looking for an answer?

Ask a questionSearch for more help

Was this helpful?
 
Leave a comment


This textbox defaults to using Markdown to format your answer.

You can type !ref in this text area to quickly search our full set of tutorials, documentation & marketplace offerings and insert the link!

Try DigitalOcean for free

Click below to sign up and get $200 of credit to try our products over 60 days!

Sign up

Join the Tech Talk
Success! Thank you! Please check your email for further details.

Please complete your information!

Become a contributor for community

Get paid to write technical tutorials and select a tech-focused charity to receive a matching donation.

DigitalOcean Documentation

Full documentation for every DigitalOcean product.

Resources for startups and SMBs

The Wave has everything you need to know about building a business, from raising funding to marketing your product.

Get our newsletter

Stay up to date by signing up for DigitalOcean’s Infrastructure as a Newsletter.

New accounts only. By submitting your email you agree to our Privacy Policy

The developer cloud

Scale up as you grow — whether you're running one virtual machine or ten thousand.

Get started for free

Sign up and get $200 in credit for your first 60 days with DigitalOcean.*

*This promotional offer applies to new accounts only.