前端设计模式及应用

什么是设计模式

设计模式是一套被反复使用、多数人知晓的、经过分类的、代码设计经验的总结。

为什么要使用设计模式

为了代码可重用性、让代码更容易被他人理解、保证代码的可靠性和稳定性。

  • 单例模式
  • 观察者模式

1.单例模式

通过单例模式可以保证系统中,应用该模式的类只有一个实例。

常用的有

  1. 数据库连接
  2. 日志记录
  3. 工具类
  4. 提示框
  5. 全局缓存

// 创建一个单例模式类
class Singleton {
    constructor() {
        if(!Singleton.instance) {
            this.name = null
            Singleton.instance = this
        }
        return Singleton.instance
    }
    
    setName(name) {
        this.name = name
    }
    
    toString() {
        console.log(`This is Singleton toString, the name is ${this.name}.`)
    }
    
    static getInstance() {
        if (!this.instance) {
            return this.instance = new Singleton()
        }
        return this.instance
    }
}

let sing1 = Singleton.getInstance()
let sing2 = Singleton.getInstance()
let sing3 = new Singleton()
let sing4 = new Singleton()
// sing1 === sing2  true
// sing2 === sing3  true
// sing3 === sing4  true
复制代码
// 微信相关api
wx.showToast({title:"测试1"})
wx.showToast({title:"测试2"})
复制代码
// table 组件
class Table {

  /**
   * Table 构造器
   * @param selector table 容器选择器
   * @param options 属性配置
   */
  constructor(selector, options) {
    
    this.options = options
    this.selector = selector

    this.init()

    if(!Table.instance) {
      Table.instance = {}
    }
    return Table.instance[selector] = this
  }

  init() {
      console.log(`Table init selector is ${this.selector}.`)
  }

  static getInstance(selector) {
    if (!this.instance) {
      this.instance = {}
    }
    if(!this.instance[selector]) {
      return this.instance[selector] = new Table(selector, options)
    }
    return this.instance[selector]
  }
}
复制代码

2. 观察者模式模式

被观察者本身状态改变是主动发出通知

常用的有

  1. vue实现原理
  2. 微信小程序setData

function defineReactive(data, key, val) {
    observe(val); // 递归遍历所有子属性
    var dep = new Dep(); 
    // 监听值set/get操作
    Object.defineProperty(data, key, {
        enumerable: true,
        configurable: true,
        get: function() {
            if (Dep.target) {  // 判断是否需要添加订阅者
                dep.addSub(Dep.target); // 在这里添加一个订阅者
            }
            return val;
        },
        set: function(newVal) {
            if (val === newVal) {
                return;
            }
            val = newVal;
            console.log('属性' + key + '已经被监听了,现在值为:“' + newVal.toString() + '”');
            dep.notify(); // 如果数据变化,通知所有订阅者
        }
    });
}
Dep.target = null;

function observe(data) {
    if (!data || typeof data !== 'object') {
        return;
    }
    Object.keys(data).forEach(function(key) {
        defineReactive(data, key, data[key]);
    });
};

Dep.target = null;

function Dep () {
    this.subs = [];
}
Dep.prototype = {
    addSub: function(sub) {
        this.subs.push(sub);
    },
    notify: function() {
        this.subs.forEach(function(sub) {
            sub.update();
        });
    }
};

function Watcher(vm, exp, cb) {
    this.cb = cb;
    this.vm = vm;
    this.exp = exp;
    this.value = this.get();  // 将自己添加到订阅器的操作
}
 
Watcher.prototype = {
    update: function() {
        this.run();
    },
    run: function() {
        var value = this.vm.data[this.exp];
        var oldVal = this.value;
        if (value !== oldVal) {
            this.value = value;
            this.cb.call(this.vm, value, oldVal);
        }
    },
    get: function() {
        Dep.target = this;  // 缓存自己
        var value = this.vm.data[this.exp]  // 强制执行监听器里的get函数
        Dep.target = null;  // 释放自己
        return value;
    }
};

function VueDemo (data, exp) {
    this.data = data;
    observe(data);
    console.log("init data:", this.data[exp]);  // 初始化模板数据的值
    new Watcher(this, exp, function (value) {
        console.log("from Watcher:", value)
    });
    return this;
}
复制代码
// example
 let data = {
    name: 'hello world'
};
var vueDemo = new VueDemo(data, 'name');
复制代码

THE END!

转载于:https://juejin.im/post/5cc1bc496fb9a0322d048d0d

你可能感兴趣的:(前端设计模式及应用)