关于W3Cschool定义的设计模式--常用的9种设计模式的介绍

一、设计模式

tip:每种设计模式,其实都是为了更高效的,更方便的解决在面对对象编程中所遇到的问题。

什么是设计模式:

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

为什么使用设计模式:

为了代码的可重用性、让代码更容易被他人理解、保证代码的可靠性。设计模式使代码的编写真正的工程化;设计模式是软件工程的基石脉络,如同大厦的结构。

有哪些设计模式(来自W3Cschool,23种):

构造器模式,模块化模式,暴露模块模式,单例模式,中介者模式,原型模式,命令模式,外观模式,工厂模式,Mixin模式,装饰模式,亨元(Flyweight)模式,MVC模式,MVP模式,MVVM模式,组合模式,适配器模式,外观模式,观察者模式,迭代器模式,惰性初始模式,代理模式,建造者模式.

二、工厂模式

  看工厂模式我们首先要看几个原理。

 (1)new的原理:

  1.创建了一个新的空对象。

  2.将这个对象的__proto__和函数的prototype做连接。

  3.将这个函数中的this改变,指向new新创建的对象。

  4.检测函数有没有有返回对象,没有返回对象,就返回new创建的对象。

 (2)构造函数的原理、特征和注意事项:

  1.构造函数,构造自定义的函数,会在函数中使用this、找到被构造出来的对象。

  2.隐患:一旦构造函数被直接执行,会错误的产生大量的全局变量。

  3.解决隐患:但是解决不了。

  4.自我约束:构造函数不要直接执行。

  5.防止误操作:行业习惯:为了防止构造函数被直接执行,产生大量的全局变量,一般将需要被构造的函数的首字母大写,以此标志构造函数和正常函数的区别。

  工厂模式(构造函数模型)基础语法:

    function Fn(){
        this.name = "root";
    }
    var f = new Fn()
    console.log(f.name)//root

三、单例模式

  单例:单个实例new出来的对象,多次new只有一个对象。

  1、多次new为什么产生一个对象呢?(new的原理)

  (1).创建了一个新的空对象。

  (2).将这个对象的__proto__和函数的prototype做连接。

  (3).将这个函数中的this改变,指向new新创建的对象。

    (4).检测函数有没有有返回对象,没有返回对象,就返回new创建的对象。

  2.针对默认情况,单独做出修改。

  3.优化全局空间。

  4.不要覆盖或修改默认属性。

单例模式

//单个实例,只有一个对象

//多次创建,返回同一个对象

function fn(){
    if(!fn.obj) { //给函数添加一个属性。 因为函数是全局的,所以该属性一旦添加一直存在;
         fn.obj = {
             name : “liyang"
         };
    }
    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()

  

使用组合模式组织起来的对象具有出色的层次结构,每当对顶层组合对象执行一个操作的时候,实际上是在对整个结构进行深度优先的节点搜索。但是这些优点都是用操作的代价换取的,比如每次顶级执行一次show方法,实际的操作就是整个树形结构的节点都会被遍历一次。但是组合对象的每个对象之间的耦合非常松散,可以简单的操作处理复杂的结果。

简单的说,组合模式是讲一批子对象组织为树形结构,一条顶层的命令会在操作树中所有的对象。提高了代码的模块化程度,对于动态的HTML界面具有很强的适用性

五、观察者模式

  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);

          //适配器的意义,多数应用在系统接口使用,也就是别人提供了一个功能,但要求传入一个A类型的参数

          //而我们手里的数据是B类型的,如果我们想使用这个功能。那么有两种解决办法:

          //第一,把自己的原代码进行修改,让B类型改为A类型,这是非常蠢的做法。

          //第二,我们把B类型的数据进行一个包装,让它看起来符合类型A,这个包装函数,就是适配器。

八、抽象工厂模式

  在工厂模式中,将多个实例的相同属性或方法,再次抽象成一个公共对象,从公共对象上,再次创建出具体的实例。

  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

总结:这就是我们平时常用的九种设计模式,每种设计模式其实都是见名识义,很多种设计模式我们也只会在写一些大型的项目的时候我们才会使用,每一种设计模式我们都需要根据当前的实际需求,来判断我们该使用哪种设计模式,使我们的代码解构更强。

原文地址:https://www.cnblogs.com/xushipobk/p/11565400.html

时间: 2024-10-11 02:27:39

关于W3Cschool定义的设计模式--常用的9种设计模式的介绍的相关文章

iOS开发中常用的几种设计模式

下面是iOS开发中比较常用的几种设计模式.详情如下所示: (一)代理模式 应用场景:当一个类的某些功能需要由别的类来实现,但是又不确定具体会是哪个类实现.优势:解耦合敏捷原则:开放-封闭原则实例:tableview的 数据源delegate,通过和protocol的配合,完成委托诉求.列表row个数delegate自定义的delegate (二)观察者模式应用场景:一般为model层对,controller和view进行的通知方式,不关心谁去接收,只负责发布信息.优势:解耦合敏捷原则:接口隔离原

设计模式小计——23种设计模式3

责任链模式Chain of Responsibility 使多个对象都有机会处理请求,从而避免请求的发送者和接受者间的耦合关系,并沿着这条链传递请求,直到有对象处理它为止 责任链模式关键是建立链接关系,在链中决定谁来处理请求 //抽象处理者 public abstract class Handle{ private Handle nextHandle;//链的下一个节点 public final Response handleMessage(Request request){ Response

设计模式小计——23种设计模式1

单例模式Singleton Pattern 确保类只有一个实例,而且自行实例化并向整个系统提供这个实例 public class Singleton{ private static final Singleton singleton = new Singleton(); private Singleton(){} public static Singleton getSingleton(){ return singleton; } } 节省内存开支,减少性能开销,应用启动产生单例对象,永久驻留内

设计模式小计——23种设计模式2

模板方法模式Template Method Pattern 定义一个操作的算法的框架,是的子类可以不改变算法结构即可重定义该算法一些特定步骤 public abstract class AbstractClass{//抽象模板类 protected abstract void method1();//算法步骤1 protected abstract void method2();//算法步骤2 public void templateMethod(){//模板方法,定义算法结构 this.met

PHP常用的三种设计模式

本文为大家介绍常用的三种php设计模式:单例模式.工厂模式.观察者模式,有需要的朋友可以参考下. 一.首先来看,单例模式 所谓单例模式,就是确保某个类只有一个实例,而且自行实例化并向整个系统提供这个实例,即在应用程序中只会有这个类的一个实例存在.通常单例模式用在仅允许数据库访问对象的实例中,从而防止打开多个数据库连接,单例模式是一种常见的设计模式,在计算机系统中,线程池.缓存.日志对象.对话框.打印机.数据库操作.显卡的驱动程序常被设计成单例. 一个单例类应包括以下几点:和普通类不同,单例类不能

JAVA设计模式总结之23种设计模式

一.什么是设计模式                                                                                                                                        设计模式(Design pattern)是一套被反复使用.多数人知晓的.经过分类编目的.代码设计经验的总结.使用设计模式是为了可重用代码.让代码更容易被他人理解.保证代码可靠性. 毫无疑问,设计模式于己于他人于

最常用的四种设计模式

下面列举四种最常用的设计模式 一.Strategy模式 1.两大原则 Strategy 模式体现了如下的两大原则: 1,针对接口编程,而不是针对实现编程. 2,多用组合,少用继承. 2. 例子: 二.Iterator模式  提供一种方法顺序访问一个聚合对象中各个元素, 而又不需暴露该对象的内部表示. 这种设计模式非常普遍, 比如Java里面的: public interface Iterator { boolean hasNext(); Object next(); void remove();

java:常用的两种设计模式(单例模式和工厂模式)

一.单例模式:即一个类由始至终只有一个实例.有两种实现方式(1)定义一个类,它的构造方法是私有的,有一个私有的静态的该类的变量在初始化的时候就实例化,通过一个公有的静态的方法获取该对象.Java代码 1. //单例模式的第一种形式    2. public class Singleton01 {    3.    4.     // 私有的静态属性    5.     private static Singleton01 instance = new Singleton01();    6.  

js对象定义的最常用的三种方法

定义对象:属性和方法的结合体(变量和函数的结合体) 1.(***)var obj = {} 2.var obj = new Object(); 3.使用function定义对象 具体例子分别为: 1 // 1.定义obj的对象 2 // obj:对象名 3 var obj = { 4 // height,weight,sex称为对象的属性 5 height: 170, // 使用,分隔属性和方法 6 weight: 90, 7 sex: '大美女', 8 9 // say():称为对象的方法 1