美文网首页
js-设计模式(总结)

js-设计模式(总结)

作者: Jianshu9527 | 来源:发表于2016-11-12 10:41 被阅读55次
1.什么叫做设计模式(基本概念)
  • 在面向对象软件设计过程中,针对问题进行简洁而优雅的一种解决方案
  • 设计模式是在某种场合下对某个问题的一种解决方案
  • 设计模式是在1995年初步形成,共有23种模式
①:创建型模式:单例模式,抽象工厂模式,建造者模式,工厂者模式,原型模式
②:结构型模式:适配器模式,桥接模式,装饰模式,组合模式,外观模式,亨元模式,代理模式,
③:行为型模式:模板方法模式,命令模式,迭代器模式,观察者模式,中介者模式,备忘录模式,解释器模式,状态模式,策略模式,职责链模式,访问者模式。

2.设计模式能干什么

  • 设计模式最大的功绩就是:把已经存在好的设计提炼出来,并取了一个号的名字(GoF)

设计模式-创建型模式(之工厂者模式)

案列-四则运算

  • 基本版本↓
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
    <style>
        input[type="text"]{
            width: 100px;
        }
    </style>
</head>
<body>
    <div style="width:500px;height:80px;margin:50px auto;border:2px solid #ddd;">
        <input type="text" id="num1">
        <select name="" id="operator">
            <option value="+">+</option>
            <option value="-">-</option>
            <option value="*">*</option>
            <option value="/">/</option>
        </select>
        <input type="text" id="num2">
        <input type="button" value='计算' id='btn'>
        <input type="text" id="result">
    </div>
    <script>
        function $(id){
            return document.getElementById(id);
        }
        
        $('btn').onclick=function(){
            //收集信息
            var num1 = $("num1").value;
            var num2 = $("num2").value;

            //正则验证
            var reg = /^[1-9]\d*$/;//正整数
            if(reg.test(num1) && reg.test(num2)){
                num1 = parseFloat(num1);
                num2 = parseFloat(num2);
                var op = $("operator").value;
                var result;
                //计算
                
                if("+" == op){
                    result = num1 + num2;
                }
                else if("-" == op){
                    result = num1 - num2;
                }
                else if("*" == op){
                    result = num1 * num2;
                }
                else if("/" == op){
                    result = num1 / num2;
                }
                //显示结果
                $("result").value = result;
                console.info(num1,num2,op);
            }
            else{
                alert("请输入正整数")
            }
        }
    </script>
</body>
</html>

分析:在给一个运算符添加新功能时,会有一个安全隐患:全部的代码暴露在当前的程序员面前,同时,相当与是在修改源代码的方法去拓展一个新功能,但是这不符合“对修改关闭原则”

  • 使用面向对象的版本↓
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
    <style>
        input[type="text"]{
            width: 100px;
        }
    </style>
</head>
<body>
    <div style="width:500px;height:80px;margin:50px auto;border:2px solid #ddd;">
        <input type="text" id="num1">
        <select name="" id="operator">
            <option value="+">+</option>
            <option value="-">-</option>
            <option value="*">*</option>
            <option value="/">/</option>
            <option value="%">%</option>
        </select>
        <input type="text" id="num2">
        <input type="button" value='计算' id='btn'>
        <input type="text" id="result">
    </div>
    <script>
        function Add(num1,num2){
            this.num1 = num1;
            this.num2 = num2;
        }
        Add.prototype.getResult = function(){
            return this.num1 + this.num2;
        }
        function Mul(num1,num2){
            this.num1 = num1;
            this.num2 = num2;
        }
        Mul.prototype.getResult = function(){
            return this.num1 * this.num2;
        }
        function Div(num1,num2){
            this.num1 = num1;
            this.num2 = num2;
        }
        Div.prototype.getResult = function(){
            if(this.num2 == 1){
                return this.num1;
            }
            return this.num1 / this.num2;
        }
        function Sub(num1,num2){
            this.num1 = num1;
            this.num2 = num2;
        }
        Sub.prototype.getResult = function(){
            return this.num1 - this.num2;
        }
        function Mod(num1,num2){
            this.num1 = num1;
            this.num2 = num2;
        }
        Mod.prototype.getResult = function(){
            return this.num1 % this.num2;
        }
        function $(id){
            return document.getElementById(id);
        }
        /**
         * 功能:计算器
         * @param  {[type]} op   [操作符]
         * @param  {[type]} num1 [第一个操作数]
         * @param  {[type]} num2 [第二个操作数]
         * @return {[type]}      [返回结果]
         */
        function computer(op,num1,num2){
            var c;
            if("+" == op){
                c = new Add(num1,num2);
            }
            else if("-" == op){
                c = new Sub(num1,num2);
            }
            else if("*" == op){
                c = new Mul(num1,num2);
            }
            else if("/" == op){
                c = new Div(num1,num2);
            }
            else if("%" == op)
                c = new Mod(num1,num2);
            
            return c.getResult();
        }
        /**
         * 正则验证
         * @param  {[type]} type [类型]
         * @param  {[type]} str  [要验证的字符串]
         * @return {[type]}      [验证结果]
         */
        function reg(type,str){
            if( "number" == type){
                var reg = /^[1-9]\d*$/;//正整数
                return reg.test(str);
            }
            else if("email" == type ){
                var reg = /^\w+@\w+(\.[a-z]{2,3})+$/i;
                return reg.test(str);
            }
        }
        $('btn').onclick=function(){
            //收集信息
            var num1 = $("num1").value;
            var num2 = $("num2").value;
            //正则验证
            if(reg("number",num1) && reg("number",num2)){
                num1 = parseFloat(num1);
                num2 = parseFloat(num2);
                var op = $("operator").value;

                //计算
                var result = computer(op,num1,num2);
                
                //显示结果
                $("result").value = result;
                console.info(num1,num2,op);
            }
            else{
                alert("请输入正整数")
            }
        }
    </script>
</body>
</html>

分析:

  • ①四个单独的运算器对象都可以在其他地方重复使用。
    ②在对新功能进行拓展的时候,不需要去暴露 其他功能的具体实现细节
    ③一个构造器就是一个单独的文件,它不会影响其他功能的构造器
    总结:编写一个工厂函数,根据输入,返回特定的对象

设计模式-创建型模式(之单例模式)

  • js字面量对象就是单例模式
    需求:让一个构造器只产生一个对象
    案列-按钮的单次点击(只能进行一次点击)
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
    <style>
    </style>
</head>
<body>
    <input type="button" value="anniu" id="btn">
    <script>
        function $(id){
            return document.getElementById(id);
        }
        //arguments
        function f(){
            console.info("我是事件响应函数");
        }
        function one(func){

            var isclicked;
            function f1(){
                if(!isclicked){
                    func();
                    isclicked = true;
                }
            }
            return f1;
        }
        $('btn').onclick=one(f);    
    </script>
</body>
</html>

总结:构造器的返回值,以及闭包的使用是对单例模型实现的一个完美体现

设计模式-行为模式(策略模式)

定义:把一系列的算法,封装起来,并且可以使它们可以相互替换
需求:给定一个值,进行求值
案列:计算公司员工的年终奖

<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
</head>
<body>
    <script>

//  公司的年终奖是根据工资基数和绩效来发放的。例如绩效为S的员工有4倍工资。A的员工有3倍工资。B的员工有2倍工资。
// 请你给出代码
        var salary = {
            S:function(basic){
                return 4 * basic;
            },
            A:function(basic){
                return 3 * basic;
            },
            B:function(basic){
                return 2 * basic;
            },
            C:function(basic){
                return 1.5 * basic;
            }
        };
        function getSalary(level,basic){
            //var f1 = salary[level];
            //return f1(basic);
            
            return salary[level](basic);
        }
        console.info ( getSalary("S",10000) );
        console.info ( getSalary("B",8000) );
        console.info ( getSalary("C",6000) );
        // console.info( salary("S",10000) );
        // console.info( salary("C",6000) );
        //问题:加一个等级C 1.5系数
    </script>
</body>
</html>

总结:①保证了对修改的关闭,同时对拓展开放
②保证了代码之间的相互不影响

设计模式-行为模式(策略模式)

定义:观察者模式又叫发布订阅模式(Publish/Subscribe),它定义了一种一对多的关系,让多个观察者对象同时监听某一个主题对象,这个主题对象的状态发生变化时就会通知所有的观察者对象,使得它们能够自动更新自己。

  • 实现原理
    观察者1,观察者2......
    中心点
    添加对象
    删除观察者
    发布更新指令(通知所有的观察者)
    容器:保存观察者的数据
  • 理论事例
    案列
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>观察者模式</title>
</head>
<body>
    <h1 id='header'>消息列表1条</h1>
    <ul id="list">
        <li>
            消息内容<br><br>
            <button value='删除' id='del'>删除</button>
        </li>
    </ul>
    <input type="text" id='news'>
    <button value='点击添加消息' id='btn'>点击添加消息</button>
</body>
<script>
    function $(id){
        return document.getElementById(id);
    };
    var counts=1;
    $('del').onclick=function(){
        counts--;
        this.parentNode.parentNode.removeChild(this.parentNode);
        $('header').innerHTML="消息列表"+counts+"条"
    }

    $('btn').onclick=function(){    
        var news=document.createElement('li'),
        del=document.createElement('button');
        news.innerHTML=$('news').value+'<br><br>';
        del.innerHTML="删除";
        del.onclick=function(){
            counts--;
            this.parentNode.parentNode.removeChild(this.parentNode);
            $('header').innerHTML="消息列表"+counts+"条"
        }
        news.appendChild(del);
        $('list').appendChild(news);
        counts++;
        $('header').innerHTML="消息列表"+counts+"条";
    }
    </script>
</html>
  • 实践操作
<html>
<head>
    <meta charset="utf-8" />
    <title></title>
    <style>
            .container{
                border:3px solid #ccc;
                padding:0 20px;
                margin:30px auto;
                width: 600px;
            }
            a{
                text-decoration: none;
            }
            ul{list-style: none;}
        </style>
</head>
<body>
    <div class="container">
        <h1>消息列表<span id="num">0</span>条</h1>
        <ul id="ulmsg">
            <!-- <li><p>消息内容</p><button>删除</button></li> -->
        </ul>
        <form action="">
            <input type="text" id="words">
            <input type="button" value="添加" id="btnsubmit">
        </form>
    </div>
    <script type="text/javascript">
        function $(id){
            return document.getElementById(id);
        }
        function create(flag){
            return document.createElement(flag)
        }
        //实现观察者
        function NumberManager(data){
            $("num").innerHTML = $("num").innerHTML*1 + data.num;
        }
        function MessageManager(data){
            //<li><p>消息内容</p><button>删除</button></li>
            var li = create("li");
            var p = create("p");
            var button = create("button");
            button.innerHTML="删除";

            button.onclick = function(){
                $("ulmsg").removeChild(li);
                
                center.fire("delMsg",{num:-1});
            }
            p.innerHTML = data.txt;
            li.appendChild(p);
            li.appendChild(button);
            $("ulmsg").appendChild(li);
        }
        function Somthingelse(data){
            console.info(data);
        }
        var center = {
            viewers:{},
            addViewer:function(eventtype,callback){
                if(this.viewers.hasOwnProperty(eventtype)){
                    this.viewers[eventtype].push(callback);
                }
                else{
                    this.viewers[eventtype] = [callback];
                }
            },
            delViewer:function(){
            },
            fire:function(eventtype,data){ //有变化 通知所有的观察者
                if(this.viewers.hasOwnProperty(eventtype)){
                    for (var i = 0; i < this.viewers[eventtype].length; i++) {
                        this.viewers[eventtype][i].call(this,data);
                    }
                }

            }
        }
        center.addViewer("addMsg",Somthingelse); //添加订阅者
        center.addViewer("addMsg",NumberManager);
        center.addViewer("addMsg",MessageManager);
        center.addViewer("delMsg",NumberManager);
        $("btnsubmit").onclick = function(){
            var data={
                txt:$("words").value,
                num:1
            };

            center.fire("addMsg",data);
        }
    </script>
</body>
</html>

设计模式-结构型模式(装饰者模式)

  • 常见的需求
    给对象动态地添加职责。在不改变对象自身的基础上,在程序运行期间给对象添加功能。比继承更灵活。
  • 阐述思路
    在不影响之前的代码下,给其添加新功能
  • 问题的解决
<html>
<head>
    <meta charset="utf-8" />
    <title></title>
    <script src="jquery-2.1.4.js"></script>
</head>
<body>

    <script type="text/javascript">

    function ready(f){
    debugger;
        //判断一下window.onload是否存在 。如果存在 ,则先调用它,再调用f函数
        var t = window.onload;
        if(typeof t =="function"){
            window.onload = function(){
                t();
                f();
            }
        }
        else{
            window.onload = function(){
                f();
            }
        }
    }
    ready(function(){console.info(2)});
    ready(function(){console.info(3)});
    ready(function(){console.info(1)});
    </script>
</body>
</html>

3.设计模式的利与弊
4.关于自学设计模式的浅略总结(坑)
设计模式“可复用面向对象软件的基础”。
设计模式完全是从面向对象设计的角度出发的,通过对封装、继承、多态、组合等技术的反复使用,提炼出一些可重复使用的面向对象设计技巧。所以有一种说法是设计模式仅仅是就面向对象的语言而言的。

相关文章

  • js-设计模式(总结)

    1.什么叫做设计模式(基本概念) 在面向对象软件设计过程中,针对问题进行简洁而优雅的一种解决方案 设计模式是在某种...

  • JS-设计模式

    设计模式:代码经验的总结设计模式都是面向对象的 工厂模式 工厂函数就是做一个对象创建的封装,并将创建的对象retu...

  • 设计模式之创建型

    设计模式概述 基于设计原则,GoF(设计模式总结4人组)总结了软件开发领域的23个经典设计模式。虽然GoF设计模式...

  • 设计模式之结构型

    设计模式概述 基于设计原则,GoF(设计模式总结4人组)总结了软件开发领域的23个经典设计模式。虽然GoF设计模式...

  • 设计模式之行为型

    设计模式概述 基于设计原则,GoF(设计模式总结4人组)总结了软件开发领域的23个经典设计模式。虽然GoF设计模式...

  • Java设计模式

    设计模式的优点: 1 设计模式(Design pattern)是一套被反复使用、代码设计经验的总结。使用设计模式...

  • 创建型设计模式总结

    创建型设计模式总结 Intro 前面几篇文章已经把创建型设计模式都介绍了,来做一个简单的总结。 创建型设计模式,就...

  • 设计模式大杂烩(24种设计模式的总结及学习设计模式的几点建议)

    设计模式大杂烩(24种设计模式的总结及学习设计模式的几点建议)模式分类 & 传送门 & 对比维度说明 设计原则:设...

  • 设计模式大杂烩(24种设计模式的总结及学习设计模式的几点建议)

    设计模式大杂烩(24种设计模式的总结及学习设计模式的几点建议)模式分类 & 传送门 & 对比维度说明 设计原则:设...

  • 设计模式

    设计模式之旅 图说设计模式 小猪的设计模式初涉总结 Java之美[从菜鸟到高手演变]之设计模式 Java之美[从菜...

网友评论

      本文标题:js-设计模式(总结)

      本文链接:https://www.haomeiwen.com/subject/mdhqpttx.html