Design pattern(II) - Factory pattern
Published: 2022-06-02 05:32:42


In the previous [post](https://dev.to/isoscar/design-pattern-i-4f31), 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
```js
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)
}
```

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)

```js
class UserFactory {
  constructor(name, age, career) {
    this.name = name
    this.age = age
    this.career = career
  }
  getPermission() {
    console.log("I am abstract factory")
  }
}
```
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

```js
class Programmer extends UserFactory {
  constructor(name, age, career) {
    super(name, age, career)
  }
  getPermission() {
    return new labPermission()
  }
}
```

```js
class Permission {
  checkIdentity() {
    console.log("I am abstract product")
  }
}

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

```

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

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

const programmerPermission = programmerOne.getPermission()

programmerPermission.checkIdentity()
//Identity checked, programmer
```

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.