Adapter & finisher

Keywords: Javascript Front-end ECMAScript

js design pattern - adapter pattern, decorator pattern

1. Adapter mode

Adapter mode: (adapter) is to convert the interface of a class into another interface desired by the customer. The adapter mode enables those classes that cannot work together due to incompatible interfaces to work together. (big talk design mode)
Usage scenario: when the data and behavior of the system are correct, but the interface is inconsistent, we should consider using an adapter to match an original object outside the control range with an interface. The adapter pattern is mainly used when you want to reuse existing classes, but the interface is inconsistent with the requirements of the environment. (big talk design mode)
JavaScript is not a traditional object-oriented language after all, so the adapter created with es6 class keyword (without typescript) will be slightly different from the adapters of Java, C#, VB.NET (not discussed in this article).

1.1 specific adapter mode

  class MyInterface {
    constructor(arr) {
      this.arr = arr
    }
    getResult() {
      return this.arr
    }
  }
  class MySonInterface extends MyInterface {
    transform() {
      return this.arr.reduce(function(pre,cur,index,arr) {
        pre['date' + index] =  cur
        return pre
      },{})
    }
  }
  var int = new MyInterface([7,2,3,4,5]) 
  var myint = new MySonInterface([7,2,3,4,5])
  console.log(int.getResult()); // [7, 2, 3, 4, 5]
  console.log(myint.transform()); // {date0: 7, date1: 2, date2: 3, date3: 4, date4: 5}

1.2 universal adapter mode

  class Adapter{
    constructor(arr) {
      this.obj = new MyInterface(arr)
    }
    transform() {
      return this.obj.arr.reduce(function(pre,cur,index,arr) {
        pre['date' + index] =  cur
        return pre
      },{})
    }
  }
  var ide = new Adapter([7,2,3,4,5])
  console.log(ide.transform()); // {date0: 7, date1: 2, date2: 3, date3: 4, date4: 5}

1.3 factory adapter mode

  class AdapterFactor {
    static create (Interface, arr) {
      return new Interface(arr)
    }
  }
  var ide2 = AdapterFactor.create(Adapter, [7,2,3,4,5])
  console.log(ide2.transform()); // {date0: 7, date1: 2, date2: 3, date3: 4, date4: 5}

2. Decorator mode

Decorator Pattern: decorator pattern allows an existing object to add new functions without changing its structure. It makes it more elegant to share or extend some methods or behaviors between different classes or objects
Usage scenario:

2.1 inheritance instance( ❌)

Why write a wrong example?
reason:
1. In the traditional object-oriented syntax, when we need to add functions to an object, we usually use class inheritance to make an object of a certain class have a certain function.
2. Decorator: dynamically add some additional responsibilities to an object. In terms of adding functions, decorator mode is more flexible than generating subclasses. (big talk design mode)

  class Cat {
    constructor(name) {
      this.name = name
    }
    sayName() {
      console.log('What's the cat's name',this.name);
    }
  }
  class SuperCat extends Cat {
    constructor(name,age) {
      super(name)
      this.age = age
    }
    sayAge() {
      console.log('Super cat this year',this.age);
    }
  }
  var cat1 = new Cat('be homesick')
  var nbCat = new SuperCat('Si fan',2)
  nbCat.sayName() //The cat's name is sifan
  nbCat.sayAge()  //Super cat 2 this year
  cat1.sayName() //The cat's name is homesickness

Because of the strong coupling brought about by inheritance, the generated class also has the fatal disadvantage of "low flexibility". When we modify a property of the parent class, the child class will change accordingly. From this, we can see the difference between class inheritance and decorator mode (if you don't understand it, please see the definition of decorator mode)

2.2 example of decorator mode

  class Dog {
    constructor(name) {
      this.name = name
    }
    sayName() {
      console.log('What's the dog's name',this.name);
    }
  }
  class SuperDog {
    constructor(dog) {
      this.dog = dog
    }
    sayName() {
      this.dog.sayName()
    }
    sayNewname() {
      console.log('The upgraded super dog has a new name','super' + this.dog.name );
    }
  }
  var dog = new Dog('Wangcai')
  var superDog = new SuperDog(dog)
  superDog.sayName() //The dog's name is Wangcai 
  superDog.sayNewname() // The upgraded super dog has a new name, super Wangcai
  dog.sayName() //The dog's name is Wangcai 

From the above results, we can see that when we call the superDog method, we not only call the superDog method, but also call the Dog method. We just wrap the Dog so that we can define the new method while using the internal methods of the Dog class

Posted by tkj on Fri, 12 Nov 2021 01:54:21 -0800