1.单例模式
定义
一个类只产生唯一的实例
实现
-
es5
function Single(name) { this.instance = null; this.name = name; this.init(); } Single.prototype.init = function() { console.log(this.name) } Single.getInstance = function(name) { if (!this.instance) { this.instance = new Single(name); } return this.instance; }; var a = Single.getInstance('test_a') var b = Single.getInstance('test_b') console.log(a,b,a===b)
这里会发现只打印了一次
this.name
,且this.name
为test_a
,而a和b是两个一样的对象 -
es6
class Single { constructor(name) { this.instance = null; this.name = name; this.init(); } //保证可以直接引用getInstance方法, static getInstance(name) { if (!this.instance) { this.instance = new Single(name); } return this.instance; } } var a = Single.getInstance('test_a') var b = Single.getInstance('test_b') console.log(a,b,a===b)
-
惰性单例
保证在需要的时候才创建对象实例
var single = function (name) { console.log(name) return name }; var getSingle = function (fn) { var result; return function () { return result || (result = fn.apply(this, arguments)) } } var test = getSingle(single) test('test_a'); test('test_b');
🌰
-
弹框
假设一个场景,每次点击按钮弹出一个弹框,要通过创建一个
div
实现,创建时不必每次都创建一个新的div
<button id="btn">创建</button> <script> var single = function () { var div = document.createElement("div"); div.style.border = '1px solid #000'; div.style.width = '200px'; div.style.height = '80px'; document.body.appendChild(div); return div; }; var getSingle = function (fn) { var result; return function () { return result || (result = fn.apply(this, arguments)) } } var createSingle = getSingle(single); document.getElementById("btn").onclick = function () { var div = createSingle(); //div.style } </script>
-
验证
一般经常写react项目,这中场景很少会遇到,我在想,做一些信息验证的时候是不是可以用到这种模式。
假设我有很多地方有同样的逻辑,例如验证一部分信息,当然可以调用一个公共的函数,可是如果是一个异步的逻辑,用到
Promise
,每次都要new Promise
,这样在相同的条件下就可以执行一次new Promise
就可以了。class Verify { constructor() { this.instance = null; this.conditions = null; } static getInstance(conditions) { // 验证条件 if (this.conditions !== conditions) { this.conditions = conditions; this.instance = new Promise(function (resolve, reject) { //... }) } return this.instance; } } // 其他地方调用 let promise = Verify.getInstance(/*conditions*/); promise.then((res) => { //... })
2.工厂模式
定义
简单工厂:由一个工厂对象决定创建某一产品对象类的实例
工厂方法:对产品类抽象,创建多产品类的实例
抽象工厂:对类的工厂抽象,创建产品类簇,不会创建某一类产品实例
实现
-
简单工厂模式
假如有很多类很类似,可以分为一类,我们就可以用简单工厂模式解决
var Apple = function() { this.name = 'Apple'; } Apple.prototype = { eat:function() { //... } } var Banana = function() { this.name = 'Banana'; } Banana.prototype = { eat:function() { //... } } //定义一个水果工厂 var Fruit = function(name) { switch(name){ case 'apple': return new Apple(); case 'banana': return new Banana(); } } //当需要某个具体对象时,调用水果工厂就可以 var apple = Fruit('apple')
-
工厂方法模式
var Fruit = function(type) { //第一次进入时this是window if(this instanceof Fruit) { var fruit = new this[type](); return fruit; } else { return new Fruit(type); } } //工厂方法函数的原型中创建对象 Fruit.prototype = { Apple: function() { this.name = "Apple", this.eat = function() {/* ... */} }, Banana: function() { this.name = "Banana", this.eat = function() {/* ... */} }, } var apple = Fruit('Apple');
使用工厂方法模式,产品类就变成了抽象类。每次创建新的产品类只需要修改工厂函数的原型。
-
抽象工厂模式
所谓抽象,就是父类抽象共同方法特性,但是具体实现由每个子类去实现该方式。
let Food = function(subType, superType) { //是否存在抽象类 if(typeof Food[superType] === 'function') { //缓存类 function F() {}; //继承父类属性和方法 F.prototype = new Food[superType] (); //将子类的constructor指向子类 subType.constructor = subType; //子类原型继承父类 subType.prototype = new F(); } else { throw new Error('抽象类不存在!') } } Food.Fruit = function() { this.type = 'fruit'; } Food.Fruit.prototype = { eat: function() { return new Error('抽象方法不能调用'); } } //水果子类 function Fruit(name) { this.name = name; } //抽象工厂实现WechatUser类的继承 Food(Fruit, 'Fruit'); //重写抽象方法 Fruit.prototype.eat = function() { //... } let apple = new Fruit('apple');
-
比较
工厂方法是对简单工厂的抽象
抽象工厂是在工厂方法的基础上进一步抽象
🌰
暂时想到对于功能相似组件的封装,(动态判断加载不同的组件、样式,角色权限,页面路由等等)可以用简单的工厂模式。一般不会用到抽象工厂。
3.建造者模式
定义
将一个复杂对象的构建与它的表示分离,使同样的构建过程可以创建不同的表示。
实现
//定义一个肉类
var Meat = function (name) {
this.name = name
}
Meat.prototype.getPrice = function () {
var price = 0;
switch (this.name) {
case 'Chicken':
price = 10;
break;
case 'Pork':
price = 20;
break;
case 'Beef':
price = 30;
break;
default:
break;
}
return price
}
//定义一个菜类
var Vegetables = function (name) {
this.name = name
}
Vegetables.prototype.getPrice = function () {
var _this = this;
var price = 0;
switch (this.name) {
case 'Cabbage':
price = 1;
break;
case 'Carrots':
price = 2;
break;
case 'Potatoes':
price = 3;
break;
default:
break;
}
return price
}
//定义食物类
var Food = function(meat,vegetables) {
this.meat = meat
this.vegetables = vegetables
}
Food.prototype.getPrice = function() {
var _this = this;
var meat = new Meat(this.meat)
var vegetables = new Vegetables(this.vegetables)
return meat.getPrice() + vegetables.getPrice()
}
var food = new Food('Pork','Potatoes')
food.getPrice()
主要实现分布构建一个复杂的对象,使各个部分之间相互解耦
🌰
实现一个复杂的组件,例如react中拆分组件、实现笛卡尔积(如上)
不同工种薪资计算:
var Human = function(name) {
this.name = name;
}
var Work = function(work) {
var _this = this;
(function(){
switch(work){
case 'Primary':
_this.work = 'Primary';
_this.price = 100;
break;
case 'Senior':
_this.work = 'Senior';
_this.price = 150;
break;
default:
_this.price = 0;
break;
}
})(work,_this)
}
Work.prototype.getPrice = function(time) {
return time*this.price
}
var Person = function(name,work) {
this.name = new Human(name);
this.work = new Work(work)
}
var person = new Person('Tom','Senior')
console.log(person.name.name)
console.log(person.work.work)
console.log(person.work.getPrice(10))
4.观察者模式
定义
观察者模式又称发布-订阅(Publish/Subscribe)模式,定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都将得到通知。例如dom事件,也是js和dom之间实现的一种观察者模式。
实现
function Observer() {
//订阅列表
this.subscribes = {};
}
Observer.prototype = {
//订阅事件
listen: function(eventType, fn){
var _this = this;
if(!(eventType in _this.subscribes)) {
_this.subscribes[eventType] = [];
}
_this.subscribes[eventType].push(fn);
return this;
},
// 触发事件(发布事件)
publish: function(eventType){
var _this = this;
var fns = Array.prototype.slice.call(arguments,1);
for(var i = 0; i < _this.subscribes[eventType].length; i++) {
_this.subscribes[eventType][i].apply(_this,fns);
}
return this;
},
// 删除订阅事件
remove: function(eventType, fn){
var currentEvent = this.subscribes[eventType];
var len = 0;
if (currentEvent) {
len = currentEvent.length;
for (var i = len - 1; i >= 0; i--){
if (currentEvent[i] === fn){
currentEvent.splice(i, 1);
}
}
}
return this;
}
}
//订阅事件A
var o = new Observer();
o.listen('test', function(data){
console.log(data);
});
var callback = function(data) {
console.log(data)
}
o.listen('test', callback);
o.publish('test', 'first');
o.remove('test', callback);
o.publish('test', 'second');
5.原型模式
定义
原型实例指向创建对象的类,创建新的对象可以共享原型对象的属性和方法
实现
var Food = function(name) {
this.name = name
}
Food.prototype.eat = function(){
//...
}
var food1 = new Food('food1');
var food2 = new Food('food2');
console.log(food1.eat === food2.eat)//true
//Object.create
var food = {
eat: function () { },
name:''
};
// 使用Object.create创建
var food1 = Object.create(food);
food.name = 'food1'
如果有问题,希望指出