DEV Community

Cover image for Design pattern(II) - Factory pattern
Oscar
Oscar

Posted on

Design pattern(II) - Factory pattern

In the previous post, I share the very basic concept of why we need the design pattern and the fundamental of the factory pattern.

We use the factory pattern to create objects that have same features, the example in the previous post

class User {
  constructor(name, age, career) {
    this.name = name
    this.age = age
    this.career = career
  }
}

function Factory(name, age, career) {
  let job
  switch(career) {
    case  "programmer":
     job = ['xxx', 'yyy', 'zzz']
    break;
    case  "accounting":
     job = ['abc', 'def', 'jkm']
    break;
    ...
  }
  return new User(name, age, career, job)
}
Enter fullscreen mode Exit fullscreen mode

There is an obvious defect. If there are hundreds of career's type and some of them are C-class (CEO, CTO, CXO), so they have very different job and permission. Factory would become too huge and complex to maintain.

You may think how we can create different users easier? Maybe we need a blueprint and use it to create an abstract factory. So, every real user is made from the abstract factory...

YES! That is today's main course, abstraction.

We know every employee has their name, age, career...and they have their permission to access a company's system. A employee can see own information. A human resource staff can see all employee's attendance records and A general manager may have more and more permission.

**But, even there are so much different type of employees, they are the user of the system.

So, in our abstract factory (UserFactory)

class UserFactory {
  constructor(name, age, career) {
    this.name = name
    this.age = age
    this.career = career
  }
  getPermission() {
    console.log("I am abstract factory")
  }
}
Enter fullscreen mode Exit fullscreen mode

We are not going to use UserFactory, instead we use it to create concrete factories and we can specify a user that having a specific permission

class Programmer extends UserFactory {
  constructor(name, age, career) {
    super(name, age, career)
  }
  getPermission() {
    return new labPermission()
  }
}
Enter fullscreen mode Exit fullscreen mode
class Permission {
  checkIdentity() {
    console.log("I am abstract product")
  }
}

class labPermission extends Permission {
  checkIdentity() {
    console.log("Identity checked, programmer")
  }
}

Enter fullscreen mode Exit fullscreen mode

So, if a programmer wants to access to the lab, he/she can do

const programmerOne = new Programmer()
//create programmer instance

const programmerPermission = programmerOne.getPermission()

programmerPermission.checkIdentity()
//Identity checked, programmer
Enter fullscreen mode Exit fullscreen mode

So, one day, if new accountant would like to create user's permission, only we need to do is to extend the class from the UserFactory. We do not revise it and not to worry about the problem mentioned above (Factory becomes too huge and complex to maintain.)

Summary

No matter the abstract factory or factory method, they are trying to decouple the invariable and variable part of a system.

There are four key elements in abstraction factory

  1. Abstract factory: It is a blueprint and used to defined what an object looks like, UserFactory in our case.

  2. Concrete factory: It inherits methods and features from the abstract factory. We use it to create a real object, Programmer in our case.

  3. Abstract product: In our case, the abstract product is our Permission because we use it to create a real permission. And it is same to the abstract factory, we do not use it to new or create a real object.

  4. Concrete product: Like labPermission. It is a real permission for programmer.

Thank you for your time. If you have any feedbacks, welcome to comment below.

Top comments (0)