This is the 21st day of my participation in the November Gwen Challenge. Check out the event details: The last Gwen Challenge 2021

The factory pattern

Let’s learn some common design patterns in object-oriented programming. How to implement them in TS?

A design pattern is able to solve a problem. We study design patterns, and most importantly, we know where they come from; Why it was designed this way; What problems does it solve?

Let’s start with the simplest design pattern: the factory pattern.

Take a look at this example:

// Canned oranges
class CannedOrange {}
​
// Canned apples
class CannedApple {}
​
// Eat a can
function eatCan(c: CannedApple | CannedOrange) {}let o = new CannedOrange();
eatCan(o);
Copy the code

We have cans of oranges, cans of apples, and then a way to eat a can whose input is one of these cans, and then we create an orange can and eat it.

Can you see anything that could be improved from the above example?

Type definition is a bit troublesome. When combined type is used, every time a can is added, another type needs to be added. The code coupling is relatively high.

We can define an abstract can that all cans must inherit from.

// Abstract can
abstract class Can {}
​
// Canned oranges
class CannedOrange extends Can {}
​
// Canned apples
class CannedApple extends Can {}
​
// Eat a can
function eatCan(c: Can) {}let o = new CannedOrange();
eatCan(o);
​
Copy the code

So what else is there to optimize?

We note that here we define a canned orange, is directly use the new created, here, we need to know to create canned what is the name of the class, if the file is bigger, or class distribution in other places, we are in the new, don’t know what are the cans can be created.

At this point, you can use factory mode to put the creation of the can inside the factory, let’s take a look at the factory class, and then you can implement a simple cannery.

// Abstract can
abstract class Can {}
​
// Canned oranges
class CannedOrange extends Can {}
​
// Canned apples
class CannedApple extends Can {}
​
type CanTypes = 'orange' | 'apple';
​
class CanFactory {
  static createCan(CanType: CanTypes) {
    if (CanType === 'apple') {
      return new CannedApple();
    } else if(CanType === 'orange') {
      return newCannedOrange(); }}}// Eat a can
function eatCan(c: Can) {}let p = CanFactory.createCan('apple');
eatCan(p);
​
Copy the code

Let’s try to create a can. When called, just put a quote around it and it will tell you what kinds of cans can be created. This solved the problem of not knowing the name of the tin.

Problem: Understand the factory model and calculate the production number

class Animal {
  private name: string;
  private static id = 0;
  // Factory mode workshop
  constructor(name: string) {
    this.name = name;
    Animal.id++;
  }
  getAnimalInfo() {
    return 'I'm made in a Mars factoryThe ${this.name}, the production number is${Animal.id}`; }}new Animal('panda').getAnimalInfo(); // The production number is?
new Animal('panda').getAnimalInfo(); // The production number is?
Copy the code

Answer: 1, 2

Resolution:

Factory pattern A common instantiation object pattern used to produce objects in batches.

The problem uses the factory pattern. You can take a closer look. The solution is the static properties of the class, which are shared by all instances. All numbers are 1,2.