头图

If you think the article is good, please follow, like and share!
Continue to share technical blog posts, pay attention to WeChat public account 👉🏻 Front-end LeBron

Concise and elegant solutions to specific problems in object-oriented software design - Design Patterns Design Patterns Principle: "Find where changes in the program are and encapsulate the changes"

在这里插入图片描述

Why learn design patterns?

I have been in a development position for more than a year. I have seen old projects and built a project from zero to one. With the continuous expansion of the project and business, if the code written is not designed, it will gradually become an emm... x mountain. No matter how you write it, you will think about refactoring.

在这里插入图片描述

The reason why people can go to the top of the food chain is because they can learn, summarize, and use "names" and "tools". The design pattern is not invented out of thin air, it is the best practice of programming in a certain business scenario, summed up after a lot of project practice, the summed up solution, and give it a name, it becomes a design pattern. Just like the tactics on the basketball court, the point guard often calls out the number of tactics to play, rather than directing them one by one. Concise code names are often more elegant than complicated descriptions. It's possible that you often write a program in a way that can be described, but you don't know what it's called, it may be a design pattern. So in the process of learning, we often have this feeling: ooooo! ! I often use this thing, often write it like this, it turns out that this is the xx mode!

在这里插入图片描述

Finally, why learn design patterns? Although sometimes design patterns will increase the complexity of the code and increase the cost of development, it greatly reduces the maintenance cost. It is like looking for a needle in a haystack if the books in the library are scattered in various corners in a disorderly manner; however, if they are numbered, categorized and placed in an orderly manner on the designated bookshelf, it will be much easier to find. Imagine a scene, one day, you point to a piece of code and start scolding, who wrote this x mountain! Move the mouse up, the git modification record shows, oh! I wrote it, that's fine. Hurry up to learn design patterns, and elegantly write concise, reusable, and easy-to-maintain programs~

singleton pattern

1. Ensure that a class has only one instance and provide a global access point to it

2. Mainly solve the problem that a globally used class is frequently created and destroyed, occupying memory

Implement the singleton pattern

It is not complicated to implement a concise singleton pattern. It is nothing more than saving the instance object, and the next time you get/create an object, return the previously created instance directly.

Simplest case pattern

  • Closure implementation
  • ES6 implementation
 // 利用闭包实现
var Singleton = (function () {
  var instance;
  function Instance() {}
  return function () {
    if (!instance) {
      instance = new Instance();
    }
    return instance;
  };
})();

var single1 = Singleton();
var single2 = Singleton();

console.log(single1 === single2); // true


// ES6实现
class Singleton {
  constructor() {
    if (!Singleton.instance) {
      Singleton.instance = this;
    }
    return Singleton.instance;
  }
}

const single1 = new Singleton();
const single2 = new Singleton();

console.log(single1 === single2); // true

lazy singleton

Lazy singleton: No instance creation is performed during initialization, and instance creation is performed when an instance is obtained, similar to the front-end resource lazy loading idea
 // 非惰性单例
class Tool{}
class SingleTon{
  constructor (name,...args) {
    this.name = name
    if(!SingleTon.instance){
      SingleTon.instance = new Tool(args)
    }
  }

  getName(){
    return  this.name;
  }

  static  getInstance(){
    return  this.instance;
  }
}


// 惰性单例
class Tool{}
class SingleTon{
  constructor (name) {
    this.name = name
  }

  getName(){
    return  this.name;
  }

  static  getInstance(){
    if(!this.instance){
      this.instance = new Tool(arguments)
    }
    return  this.instance;
  }
}

Transparent singletons and proxy singletons

  • transparent singleton

    • Encapsulates instance creation and method execution into a class
    • Not in line with the "single responsibility principle", the code is not easy to read and change
  • proxy singleton

    • Proxy mode: separate instance creation and method, delegate out
    • Person as a normal class can create object instances
    • createPerson creates a proxy as a singleton, you can create a singleton
    • In line with the "single responsibility principle", the code is easy to read and change
 // 透明 单例
class createPerson{
  constructor (name) {
    if(createPerson.instance){
      return createPerson.instance;
    }
    this.name = name;
    this.init();
    return createPerson.instance = this;
  }

  init(){
    console.log('My name is ',this.name)
  }
}
const p1 = new createPerson('lebron')
const p2 = new createPerson('james')
p1.init(); // My name is  lebron
p2.init(); // My name is  lebron


// 代理单例
class Person{
  constructor (name) {
    this.name = name;
  }
  init(){
    console.log('My name is ',this.name)
  }
}

class createPerson{
  constructor (name) {
    if(!createPerson.instance){
      createPerson.instance = new Person(name)
    }
    return createPerson.instance;
  }
}
const p1 = new createPerson('lebron')
const p2 = new createPerson('james')
p1.init(); // My name is  lebron
p2.init(); // My name is  lebron

final version

Every time the singleton pattern of a class is implemented, the template code that is repeated by CV is not in line with expectations.

Therefore, we can "find out where the program changes and encapsulate the changes" according to the principles of design patterns

Can be modified as follows

 class SingleTon{
  constructor (fn) {
    let singleInstance;
    function singleConstructor(...args){
      // 第一次实例化
      if(!singleInstance){
        singleInstance = new fn(...args);
      }
      // 多次实例化直接返回
      return singleInstance;
    }

    singleConstructor.prototype = Object.create(fn.prototype);
    return singleConstructor;
  }
}

class Person{
  constructor (name) {
    this.name = name;
  }
  init(){
    console.log('My name is ',this.name)
  }
}
const createPerson = new SingleTon(Person);
const p1 = new createPerson('lebron');
const p2 = new createPerson('james');
p1.init(); // My name is  lebron
p2.init(); // My name is  lebron
console.log(p1 === p2)  // true

class Tool{
  constructor (number) {
    this.number = number;
  }

  init(){
    console.log('This is tool ', this.number)
  }
}
const createTool = new SingleTon(Tool);
const t1 = new createTool(1);
const t2 = new createTool(2);
t1.init(); // This is tool  1
t2.init(); // This is tool  1
console.log(t1 === t2); // true

Application scenarios of the singleton pattern

login window

The login window is very common in our software, and it is also very suitable to be created using the singleton pattern (globally unique, frequently used)

Using the singleton pattern to create can avoid multiple node creation and destruction

 class Login {
  constructor() {
    this.element = document.createElement('div');
    this.element.innerHTML = `
           用户名 <input name="username"/>
           密码 <input name="password"/>
           <input type="submit" value="登录"/>
          `;
    this.element.style.cssText = `width:100px;height:100px;position:absolute;left:50%;top:50%;margin-top:-50px;margin-left:-50px;display:none`;
    document.body.appendChild(this.element);
  }
  show() {
    this.element.style.display = 'block';
    console.log('show');
  }
  hide() {
    this.element.style.display = 'none';
    console.log('hide');
  }
}

// 采用上文最终版本创建单例代码
const createLogin = new SingleTon(Login);
const loginInstance = createLogin();

document.getElementById('show-btn').addEventListener('click', function () {
  loginInstance.show();
});
document.getElementById('hide-btn').addEventListener('click', function () {
  loginInstance.hide();
});

Store

Global state management, globally unique instance like Vuex/Redux/Mobx
 // 已省略一些无关代码
if (!Vue && typeof window !== 'undefined' && window.Vue) {
  install(window.Vue)
}

function install (_Vue) {
  if (Vue && _Vue === Vue) {
    console.error('[vuex] already installed. Vue.use(Vuex) should be called only once.')
    return
  }
  Vue = _Vue
}

Jquery

Jquery is also the singleton mode of the application, although it has gradually faded out of our sight 😂
 if(window.jQuery!=null){
  return window.jQuery;
}else{
    //init~~~~~~~
}

Summarize

scenes to be used

  • Guarantees only one instance of a class and provides a global access point to it

advantage

  • There is only one instance in memory, which reduces memory overhead, especially when instances are created and destroyed frequently
  • Avoid multiple occupation of resources

chat

In the first half of the year, I have been busy with graduation, and then I took a break for a while. I have not written technical articles for more than half a year.

Recently, I officially joined the company and began to gradually adjust to a better learning and working state. Make some study plans and resume updating the article (I haven't written it for a long time or I'm not used to it haha

The first article of the first series "Design Patterns" took a long time to ink, but it was finally produced. The follow-up will continue to update, the update frequency and progress will depend on the free time haha, welcome to pay attention~

A front-end engineer who is still working hard, keep going!

在这里插入图片描述

Continue to share technical blog posts, welcome to pay attention!

image.png


前端LeBron
18 声望4 粉丝

字节前端工程师一枚 持续分享Web开发知识