什么是设计模式
设计模式是一套被反复使用、多数人知晓的、经过分类的、代码设计经验的总结。
为什么要使用设计模式
为了代码可重用性、让代码更容易被他人理解、保证代码的可靠性和稳定性。
- 单例模式
- 观察者模式
1.单例模式
通过单例模式可以保证系统中,应用该模式的类只有一个实例。
常用的有
- 数据库连接
- 日志记录
- 工具类
- 提示框
- 全局缓存
例
// 创建一个单例模式类
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. 观察者模式模式
被观察者本身状态改变是主动发出通知
常用的有
vue
实现原理- 微信小程序
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!