Design Patterns Handbook
  • Introduction
  • Creational Patterns
    • Builder
    • Factory
    • Abstract Factory
    • Factory Method
    • Prototype
    • Singleton
    • Object Pool
    • Revealing Constructor
  • Structural Patterns
    • Adapter
    • Composite
    • Proxy
    • Flyweight
    • Facade
    • Bridge
    • Decorator
    • Private Class Data
  • Behavioral Patterns
    • Template Method
    • Mediator
    • Chain Of Responsibility
    • Observer
    • Strategy
    • Command
    • State
    • Visitor
    • Memento
    • Interpreter
    • Null Object
    • Iterator
    • Middleware
  • Clean Code Patterns
    • Extract Method
    • Clarify Responsibility
    • Remove Duplications
    • Keep Refactoring
    • Always Unit Test
    • Create Data Type
    • Comment to Better Name
    • Consistent Naming
    • If-else over ternary operator
    • Composition over Inheritance
    • Too Many Returns
    • Private to Interface
  • Anti Patterns
    • Big Ball of Mud
    • Singleton
    • Mad Scientist
    • Spaghetti Code
    • It Will Never Happen
    • Error Codes
    • Commented Code
    • Abbreviations
    • Prefixes
    • Over Patternized
    • Generic Interface over Function
Powered by GitBook
On this page
  • Example - Animal factory
  • Example - Factory in JavaScript
  • Example - Enforce encapsulation

Was this helpful?

  1. Creational Patterns

Factory

Factory pattern becomes handy we want to dynamically create instance based on some inputs.

Example - Animal factory

Lets say we got a file of various data, it is full of cats and dogs. We want to read the file and create specific objects based on a discriminator. Something like AnimalFactory.create("DOG", "Alex").

abstract class Animal {
    public abstract String getName();
}

class Dog extends Animal {

    private String name;

    public Dog(String name) {
        this.name = name;
    }

    @Override
    public String getName() {
        return name;
    }
}

class Cat extends Animal {

    private String name;

    public Cat(String name) {
        this.name = name;
    }

    @Override
    public String getName() {
        return name;
    }
}

class AnimalFactory {

    public static Animal create(String type, String name) {
        if (type.equals("CAT")) {
            return new Cat(name);
        } else if (type.equals("DOG")) {
            return new Dog(name);
        }
        return null;
    }
}

Then we can easily create object using a static method create.

Animal cat = AnimalFactory.create("CAT", "Meow");
Animal dog = AnimalFactory.create("DOG", "Johnson");

If there are too many variables that should be passed into create method, we might want to combine this pattern with Builder pattern. When we call create method, it would return AnimalBuilder. It would become something like this:AnimalBuilder buidler = AnimalFactory.create("DOG");

Example - Factory in JavaScript

Here is an example of factory function that creates a specific instance of image class.

function createImage(name) {
  if (name.match(/\.jpeg$/)) {
    return new JpegImage(name);
  } else  if (name.match(/\.png/)) {
    return new PngImage(name);
  } else {
    throw new Error('Unsupported image format')
  }
}

class JpegImage {
  constructor(name) {
    this.name = name;
  }
}

class PngImage {
  constructor(name) {
    this.name = name;
  }
}

const jpeg = createImage('my.jpeg');
console.log(jpeg instanceof JpegImage);

const png = createImage('my.png');
console.log(png instanceof PngImage);

createImage('my.gif');

Example - Enforce encapsulation

This example shows factory method that not only creates a new instances, but also hides some properties from the user.

function createImage(name) {
  if (name.match(/\.jpeg$/)) {
    return createJpeg(name);
  } else  if (name.match(/\.png/)) {
    return createPng(name);
  } else {
    throw new Error('Unsupported image format')
  }
}

function createPng(name) {
  const privateProperties = {};

  class PngImage {
    constructor(name) {
      this.name = name;
      privateProperties.veryInternal = `very special and internal thing that nobody can change`
    }
    getSomethingSpecialThatNobodyCanModify() {
      return privateProperties.veryInternal;
    }
  }
  const image = new PngImage(name);
  return image;
}

function createJpeg(name) {
  const privateProperties = {};
  class JpegImage {
    constructor(name) {
      this.name = name;
      privateProperties.veryInternal = `another very special and internal thing that nobody can change`
    }
    getSomethingSpecialThatNobodyCanModify() {
      return privateProperties.veryInternal;
    }
  }

  const image = new JpegImage(name);

  return image;
}

const jpeg = createImage('my.jpeg');
console.log(jpeg);
console.log(jpeg.getSomethingSpecialThatNobodyCanModify());

const png = createImage('my.png');
console.log(png);
console.log(png.getSomethingSpecialThatNobodyCanModify());
PreviousBuilderNextAbstract Factory

Last updated 5 years ago

Was this helpful?