一、设计模式
tip:每种设计模式,其实都是为了更高效的,更方便的解决在面对对象编程中所遇到的问题。
function Fn(){ this.name = "root"; } var f = new Fn() console.log(f.name)//root
单例模式
//单个实例,只有一个对象 //多次创建,返回同一个对象 function fn(){ if(!fn.obj) { //给函数添加一个属性。 因为函数是全局的,所以该属性一旦添加一直存在; fn.obj = { name : “土土皮皮" }; } return fn.obj; } var obj1 = new fn(); var obj2 = new fn(); console.log(obj1 == obj2); //例如我们创建一个信息提示框,每一次执行toast方法,如果都创建一个新的元素,这样做太浪费了。 //因此,我们采取单例模式,确保无论调用多少次toast方法,都只创建一个DOM元素。 //我们只控制它的显示和隐藏,而不是每次创建每次销毁。 function Toast(){ var div = document.createElement("div"); div.className = "box"; document.body.appendChild(div); setTimeout(function(){ div.remove(); },1000) } obtn.onclick = function(){ var a = new Toast(); var b = new Toast(); console.log(a == b) } function Toast(){ if(!Toast.div){ Toast.div = document.createElement("div"); Toast.div.className = "box"; document.body.appendChild(Toast.div); clearTimeout(Toast.div.timer); Toast.div.timer = setTimeout(function(){ Toast.div.style.display = "none"; },1000) }else{ Toast.div.style.display = "block"; clearTimeout(Toast.div.timer); Toast.div.timer = setTimeout(function(){ Toast.div.style.display = "none"; },1000) } return Toast; } obtn.onclick = function(){ var a = new Toast(); var b = new Toast(); console.log(a == b); }
单例模式-弹出框案例
// 单例模式 function Toast(){ // 第一次执行函数时给构造函数添加属性为对象 if(!Toast.obj){ Toast.obj = {}; // 对对象进行加工 Toast.obj.dia = document.createElement("dialog"); Toast.obj.dia.innerHTML = "这是一个弹出框"; document.body.appendChild(Toast.obj.dia) } // 正常情况下,每次创建元素,都要立即显示 Toast.obj.dia.style.display = "block"; // 过一定的时间后,隐藏元素 clearTimeout(Toast.obj.t) Toast.obj.t = setTimeout(() => { Toast.obj.dia.style.display = "none" }, 2000); // 覆盖this的指向(覆盖new出来的对象) return Toast.obj; } document.onclick = function(){ var t1 = new Toast() var t2 = new Toast() var t3 = new Toast() var t4 = new Toast() var t5 = new Toast() //这些被new出来的对象,都指向一个对象 console.log(t1 == t2)//true console.log(t3 == t2)//true console.log(t5 == t2)//true console.log(t4 == t2)//true console.log(t1 == t3)//true console.log(t3 == t5)//true }
四、组合模式
1、组合模式是用来组合对象的,一般应用于页面,将对象按照一定的规律和关系组合,组成树状结构,类似于DOM元素中的树状结构,可以完成动态网页的生成、创建元素和修改样式。
2、将对象组合起来之后,可以实现:批量操作。
3、缺点:节省了操作,消耗了性能。
tip:组合模式最重要的是组合器。
// 最关键的是组合器: function ImagesStore( id ){ this.children = []; this.element = document.createElement("div"); this.element.id = id; document.body.appendChild(this.element) } ImagesStore.prototype = { constructor : ImagesStore, add:function( child ){ this.children.push( child ); this.element.appendChild( child.getElement() ); }, remove:function( child ){ for( var node, i=0; node = this.getChild(i); i++ ){ if( node === child ){ this.children.splice( i, 1 ); break; } } this.element.removeChild( child.getElement() ); }, getChild:function( i ){ return this.children[i]; }, show:function(){ this.element.style.border = 'solid 2px black'; for( var node, i=0; node = this.getChild(i); i++ ){ node.show(); } }, hide:function(){ for( var node, i=0; node = this.getChild(i); i++ ){ node.hide(); } this.element.style.border = 'none'; }, getElement:function(){ return this.element; } } function ImageItem( src ){ this.element = document.createElement("img"); this.element.src = src; this.element.className = "img-item"; } ImageItem.prototype = { constructor:ImageItem, add:function( child ){ console.log("这是子对象了,没有添加功能"); }, remove:function( child ){ console.log("这是子对象了,没有删除功能"); }, getChild:function( i ){ console.log("这是子对象了,没有获取子对象功能"); }, show:function(){ this.element.style.border = 'solid 2px black'; }, hide:function(){ this.element.style.border = 'none'; }, getElement:function(){ return this.element; } } var box = new ImagesStore("box"); var xbox = new ImagesStore("xbox"); var img1 = new ImageItem("https://www.baidu.com/img/bd_logo1.png") var img2 = new ImageItem("https://www.baidu.com/img/bd_logo1.png") xbox.add(img1) xbox.add(img2) box.add(xbox) // box.remove(img1) // img1.show() box.show() // img1.add()
五、观察者模式
1、观察者模式又叫发布订阅者模式:
(1)发布者:主题对象,一般只有一个。
(2)接收者:订阅者,多个,随时添加和删除。
(3)广播通信,一个对象发布信息,多个对象接收信息,并做出对应处理。
2、观察者模式的好处:
(1)支持简单的广播通信,自动通知所有已经订阅过的对象。
(2)页面载入后目标对象很容易与观察者存在一种动态关联,增加了灵活性。
(3)目标对象与观察者之间的抽象耦合关系能够单独扩展以及重用。
观察者模式-案例-看孩子还是打麻将
function child(n){ this.name = n; this.type = function(){ return Math.random()>0.5? 0 : 1; } } function mather(n,c){ this.name = n; this.child = c; this.listen = function(t){ if(t==0){ console.log(this.child.name + "哭了,"+this.name+"看孩子") }else{ console.log(this.child.name + "睡了,"+this.name+"打麻将") } } } function father(n,c){ this.name = n; this.child = c; this.listen = function(t){ if(t==0){ console.log(this.child.name + "哭了,"+this.name+"看孩子") }else{ console.log(this.child.name + "睡了,"+this.name+"打麻将") } } } var c = new child("大宝"); var t = c.type(); var m = new mather('大宝妈',c); m.listen(t); var f = new father('大宝爸',c); f.listen(t);
六、代理模式
function girl(name){ this.name = name; } function boy(girl){ this.girl = girl; this.sendGift = function(gift){ alert("你好,漂亮的"+this.girl.name+",这是我送你的:"+gift); } } function porxyLitterBrother(girl){ this.girl = girl; this.send = function(gift){ this.g = gift; gift = "一个拥抱"; var b = new boy(girl); b.sendGift(gift); } this.init = function(){ console.log(this.g) } } var g = new girl("翠花"); var p = new porxyLitterBrother(g); p.send("钻戒") p.init()
七、适配器模式
适配器模式就是将原本不具有某些功能的对象,在使用这些功能时,不出问题,并让某些不具有特征的属性,变得特征
demo:
电子工厂:手机,平板
手机:打电话,玩游戏
平板:玩游戏
测试模块只有一个:想能测平板又能测手机,还正确测试,不出问题
// 应用场景 // 让某个不具有明显特征的功能,变得有特征 function phone(){ this.name = "phone"; this.call = function(){ console.log(this.name + "可以打电话"); }; this.game = function(){ console.log(this.name + "可以打游戏"); }; } function pad(){ this.name = "pad"; this.game = function(){ console.log(this.name + "可以打游戏") } } function text(obj){ if(obj.call){ obj.call(); }else{ console.log(obj.name+"没有打电话的功能"); }; if(obj.game){ obj.game(); }else{ consloe.log(obj.name+"没有打游戏的功能"); } } var p1 = new phone(); text(p1); var p2 = new pad(); text(p2);
八、抽象工厂模式
在工厂模式中,将多个实例的相同属性或方法,再次抽象成一个公共对象,从公共对象上,再次创建出具体的实例。
demo:
造车厂:制造汽车
汽车需要车架子:轮子,引擎。
我们可以将相同的部分放一起,然后通过添加其他不同的零件,生产不行型号的车。
var f = (function (){ //抽象工厂模式主要就是这个公共对象,模具对象 function car(wheel,engine){ //内部配置函数,可以提供配置功能。 this.wheel = wheel; this.engine = engine; } return function(wheel , engine){ // 构造器, 负责创建对象。 return new car(wheel,engine); // 这是对外提供的接口,负责和外部需求连接。 } })(); var car1 = f("15","V8"); var car2 = f("13","V10"); //每次执行都会有这个公共对象,执行这个公共对象,获得一个新的对象 console.log(car1);//一个新的car对象 console.log(car2);//一个新的car对象 console.log(car1 == car2);//false
//这种模式,就是所谓的抽象工厂模式。
九、策略模式
策略:计划,规划,预制要做的事情,不同的情况定制不同的计划。
function fn(n){ if(n < 10 || n.length < 1){ return "0"+n }else{ return n; } } var num = fn(4); console.log(num)//04
总结:这就是我们平时常用的九种设计模式,每种设计模式其实都是见名识义,很多种设计模式我们也只会在写一些大型的项目的时候我们才会使用,每一种设计模式我们都需要根据当前的实际需求,来判断我们该使用哪种设计模式,使我们的代码解构更强。