Javascript 设计模式 辛格尔顿

转载请注明出处:http://blog.csdn.net/lmj623565791/article/details/30490955

我一直很喜欢Js,,,今天写JsSingleton模式来实现,以及如何使用。

1、单身写

当简单:

     var singleTon = {
            m1: "memeber first ",
            m2: "memeber second ",
            f1: function ()
            {
                console.log("fun1 ");
            }
        };

好了。结束了,事实上就是字面量创建对象的方式。非常easy吧。

假设你认为单例太简单,不用看了。那你就错了。单例在Js中用的地方挺多。话说你经经常使用么~。

2、单例使用方法一:创建命名空间

在开发中一个页面通常会引入多个Js文件,甚至这多个文件多人写的,大家都可能在全局定义init这种方法,都可能在全局声明name这是属性。这种话就造成的命名的冲突。发生一些意想不到的问题。

所以我们须要引入命名空间:

我们能够让每一个程序员写的Js在他自己的命名空间下:

/**
 * 创建命名空间
 * @type {{}}
 */
var ZhangHongYang = {};

var zhy = {};
zhy.com = {} ;
zhy.com.js = {};

比方以每一个人的名字作为命名空间,之后写方法就:ZhangHongyang.xxx();或者你习惯了Java的命名空间,也能够zhy.com.js.xxx。

3、单例实例:实现一个注冊页面的Js

针对像注冊页面上的Js,一般都是针对此页面写的,建议使用单例的方式书写。

以下的展示怎样使用单例的写法。实现ajax的注冊功能,当然没有server,模拟一下:

html:

<body>
<form action="user/register" id="registerForm">

    <div>
        <label for="username">username</label>
        <input type="text" name="username" id="username"/>
    </div>
    <div>
        <label for="nickname">nickname</label>
        <input type="text" name="nickname" id="nickname"/>
    </div>
    <div>
        <label for="password">password</label>
        <input type="text" name="password" id="password"/>
    </div>

    <div>
        <input type="submit" value="Register"/>
    </div>
</form>

<div id="registerResult" style="width: 400px;height: 200px;border: 1px solid #444;">

</div>

</body>

当用户点击submit。会进行一些列的处理。终于将数据展示到registerResult中:

 <script type="text/javascript">

        /**
         * 单例的使用方法:
         * 有时候我们须要针对某个页面进行写Js,比方登录页面,建议使用下列方式:
         * ZhangHongyang,singlePageJsForRegiste =
         * {
         *     CONSTANT1:"",
         *     CONSTANT2:"",
         *     f1:function(){},
         *     f2:function(){}
         * }
         */

        ZhangHongYang.singlePageJsForRegister =
        {
            ID_FROM: "registerForm",
            ID_RESULT_CONTAINER: "registerResult",
            init: function ()
            {
                ZhangHongYang.singlePageJsForRegister.form = $("#" + this.ID_FROM);
                ZhangHongYang.singlePageJsForRegister.result = $("#" + ZhangHongYang.singlePageJsForRegister.ID_RESULT_CONTAINER);
                this.form.submit(this.handleSubmit);
            },
            handleSubmit: function (event)
            {

                var datas = {};
                ZhangHongYang.singlePageJsForRegister.form.find("input").each(function (i)
                {
                    //omitted the unnecessary datas
                    if (!($(this).attr("type") == "button" || $(this).attr("type") == "submit" || $(this).attr("type") == "reset" ))
                    {
                        datas[$(this).attr("name")] = $(this).val();
                    }
                });
                ZhangHongYang.singlePageJsForRegister.ajaxSubmit(datas);
                //prevent the default form submit
                event.preventDefault();
            },
            ajaxSubmit: function (datas)
            {
                var url = ZhangHongYang.singlePageJsForRegister.form.attr("action");
                console.log("url :" + url);
                //make ajax submit here
                //$.post(url,datas,function(data){});
                //show result
                ZhangHongYang.singlePageJsForRegister.showResult(datas);
            },
            showResult: function (datas)
            {
                var result = "";
                for (var p in datas)
                {
                    result += p + " = " + datas[p] + "<br/>";
                }
                ZhangHongYang.singlePageJsForRegister.result.html(result);
            }
        };

        $(function ()
        {
            ZhangHongYang.singlePageJsForRegister.init();
        });

    </script>

我们使用单例定义了一个singlePageJsForRegister方法对象,然后将须要用到的元素的Id作为了常量,然后通过init初始化事件等,还有其它的几个函数。代码中也书写了凝视。看了上面的代码可能认为这么写好复杂,代码量也多了。可是对于Js的提升。要慢慢的学习面向对象以及结构化的写法,不能在script标签中。不断的定义各种方法。甚至在html标签中书写onclick这类的属性。

Js一定要保证,html与js文件解耦;js代码总体上结构清晰;学习使用面向对象的方式处理问题。

watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvbG1qNjIzNTY1Nzkx/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" >

4、怎样在单例创建的对象中,定义私有方法和属性

上述单例的写法。会把全部的方法与变量暴露给使用者。 怎样设置私有变量或者私有方法。

a、採用约定的方式:全部以_开头的方法和变量都是私有变量。

  /**
         * 方式一
         * 採用约定,全部以_开头的变量或者方法为私有变量
         */
        var singleTon = {
            _m1: "hello",
            _f1: function ()
            {
            },
            init: function ()
            {
            }
        };

能够认为方式1不是自己骗自己么,可是项目嘛,约定因为配置,也是可行的。实在认为不能忍受,看方式二:

 /**
         * 方式二
         */
        var singleTon = (function ()
        {
            var _m1 = "hello";
            var _f1 = function ()
            {
                console.log(" i am a private function !");
            }

            return {
                //public method
                init: function ()
                {
                    //invoke the private method in the singleTon
                    _f1();
                }
            };

        })();

採用了闭包的方式,非常好的实现了私有变量和私有方法的隐藏。

5、单例实例:解决Textarea的数据存储时的Html转Txt和展示时Txt转Html

在web项目中,非常多情况会使用到Textarea。

a、比方留言、技能的书写等;对于这类Textarea我们有必要对用户输入的html代码做特殊处理,防止用户填写恶意代码或者把页面的样式弄乱。

b、相反来说。在Textarea中书写的换行以及空格。终于在div中显示却没有效果,都是一个空格。全部非常多web开发人员会选择使用仅仅读textarea来回显用户输入内容,事实上须要做一定的转换。

html:

<body>
<textarea style="width: 400px;height: 120px;" id="taContent">
</textarea>

<input type="button" id="convert" value="Convert"/>
<br/>
<br/>

<fieldset style="width: 400px">
    <legend>html转化为Txt,供Div展示</legend>
<div style="width: 400px;height: 120px;border: 1px solid #555;" id="divContent">

</div>
</fieldset>

<br/>
<br/>

<fieldset style="width: 400px">
    <legend>Txt转化为Html,供Textarea改动</legend>
    <textarea style="width: 400px;height: 120px;" id="taEdit">
    </textarea>
</fieldset>

</body>

第一个Textarea用于用户输入,然后经过转义显示到div中。然后将转义后的数据进行逆向恢复显示到第二个TextArea中。相当与模拟了。div中展示数据和用户再次编辑数据。这些功能在项目中都相当有用。

我们的js代码:

  /**
         * 对用户在TextArea中输入的数据进行过滤,把< -> <等操作,以及逆向操作
         */
        ZhangHongYang.htmlFilter = (function ()
        {
            /**
             * 转化textarea中的空格为$nbsp;
             * \n转化为<br/>
             * @private
             */
            function _transSpace(data)
            {
                return data.replace(/\n/g, "<br/>").replace(/\s/g, " ");
            };

            /**
             * 转化全部尖括号
             * @private
             */
            function _transBrace(data)
            {
                return data.replace(/</g, "<").replace(/>/g, ">");
            };

            function _resumeSpace(data)
            {
                return data.replace(/ /g, " ").replace(/<br\s*\/>/ig, "\n");
            };
            function _resumeBrace(data)
            {
                return data.replace(/</g, "<").replace(/>/g, ">");
            };

            return {

                txt2Html: function (data)
                {
                    return _transSpace(_transBrace(data));

                }, html2Txt: function (data)
                {
                    return _resumeSpace(_resumeBrace(data));
                }
            };

        })();

在我的命名空间下定义了htmlFilter方法,然后最后暴露两个方法Html2Txt和Txt2Html给使用者。

调用的代码:

    <script type="text/javascript">
        $(function ()
        {
            $("#convert").click(function ()
            {
                var txt = ZhangHongYang.htmlFilter.txt2Html($("#taContent").val());
                console.log(txt);
                $("#divContent").html(txt);
                $("#taEdit").val(ZhangHongYang.htmlFilter.html2Txt(txt));
            });
        });
    </script>

效果图:

能够看到换行、空格、以及恶意的HTML代码等都得到了非常好的在DIV中的显示。且终于可还原为Textarea中供编辑;假设各位项目中没有考虑到这类问题,首先你能够測试下问题,然后能够使用上面的代码解决这类问题。

6、单例写法提高多分支代码效率

相信大家都了解过ajax,对象ajax肯定离不开XMLHttpRequest。并且不同版本号、类型的浏览器创建方式不一致。

一般我们可能会这么写创建XMLHttpRequest的方法:

  function createXhr()
        {
            var xmlhttp;
            if (window.XMLHttpRequest)
            {// code for IE7+, Firefox, Chrome, Opera, Safari
                xmlhttp=new XMLHttpRequest();
            }
            else
            {// code for IE6, IE5
                xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
            }

            return xmlhttp ;
        }

存在一个问题,每次创建XHR对象都须要进行分支推断,假设某个方法分支特别多,我们能够做进一步的优化,当浏览器载入js文件时,就决定以后调用仅仅会用当中合适的方式,而不会走分支。

我们把代码改成:

   /**
         * 用于在程序载入次js文件时,依据当前浏览器返回一个创建xhr的工厂方法,而不须要每次都去分支推断
         */
        ZhangHongYang.xhrFactroy = (function ()
        {
            function _ieCreateXhr()
            {     // code for IE6, IE5
                return   new ActiveXObject("Microsoft.XMLHTTP");
            }

            function _newCreateXhr()
            {
                // code for IE7+, Firefox, Chrome, Opera, Safari
                return new XMLHttpRequest();
            }

            if (window.XMLHttpRequest)
            {
                return _newCreateXhr;
            }
            else
            {
                return _ieCreateXhr;
            }
        })();

当程序载入完毕js文件后,会自己主动依据浏览器类型返回适合的方法,避免每次都会进行分支推断,我们仅仅须要使用ZhangHongYang.xhrFactroy();创建XHR对象。

7、单例引入懒载入功能

上述的js的文件基本在引入页面后,浏览器载入就会进行大量操作占用内存,有时候我们希望等到我们去使用时再去运行一些操作。假设从未使用就省去不必要的内存消耗,我们能够进行例如以下改写代码:

/**
         * 用于在程序载入次js文件时,依据当前浏览器返回一个创建xhr的工厂方法,而不须要每次都去分支推断
         */
        ZhangHongYang.xhrFactroy = (function ()
        {
            var _instance = null;

            function _constructor()
            {
                function _ieCreateXhr()
                {     // code for IE6, IE5
                    return   new ActiveXObject("Microsoft.XMLHTTP");
                }

                function _newCreateXhr()
                {
                    // code for IE7+, Firefox, Chrome, Opera, Safari
                    return new XMLHttpRequest();
                }

                if (window.XMLHttpRequest)
                {
                    return _newCreateXhr;
                }
                else
                {
                    return _ieCreateXhr;
                }
            }

            return {getInstance: function ()
            {
                if (_instance == null)
                {
                    _instance = _constructor();
                }
                return _instance;

            }};

        })();
<script type="text/javascript">

        var xhrFactoryMethod = ZhangHongYang.xhrFactroy.getInstance();
        console.log(xhrFactoryMethod());

    </script>

仅仅有使用时才会去运行_constructor()方法,而不是我们之前的一载入完毕就运行。

好了。js的单例模式已经经常使用的方法介绍完了。以后在书写js代码时,能够尝试使用上述的方法进行书写,而不是大量定义全局function以及变量。请不要在html标签中添加事件处理的代码~

假设存在不论什么问题,或者有不论什么问题请留言~

版权声明:本文博客原创文章,博客,未经同意,不得转载。

时间: 2024-08-05 19:28:54

Javascript 设计模式 辛格尔顿的相关文章

JavaScript设计模式 - 迭代器模式

迭代器模式是指提供一种方法顺序访问一个聚合对象中的各个元素,而又不需要暴露该对象的内部表示. 迭代器模式可以把迭代的过程从业务逻辑中分离出来,在使用迭代器模式之后,即使不关心对象的内部构造,也可以按顺序访问其中的每个元素 许多浏览器都支持 Javascript 的 Array.prototype.forEach 迭代器可以分为 内部迭代器 和 外部迭代器 一.jQuery 中的迭代器 1 $.each( [1,2,3,4], function (i, n) { 2 console.log( "当

javascript设计模式详解之命令模式

每种设计模式的出现都是为了弥补语言在某方面的不足,解决特定环境下的问题.思想是相通的.只不过不同的设计语言有其特定的实现.对javascript这种动态语言来说,弱类型的特性,与生俱来的多态性,导致某些设计模式不自觉的我们都在使用.只不过没有对应起来罢了.本文就力求以精简的语言去介绍下设计模式这个高大上的概念.相信会在看完某个设计模式之后有原来如此的感慨. 一.基本概念与使用场景: 基本概念: 将请求封装成对象,分离命令接受者和发起者之间的耦合. 命令执行之前在执行对象中传入接受者.主要目的相互

javascript设计模式

javascript设计模式 阅读目录 什么是设计模式 单体模式: 工厂模式: 单例模式 观察者模式(发布订阅模式) 策略模式 模板模式 代理模式 外观模式 设计模式太多了,貌似有23种,其实我们在平时的工作中没有必要特意去用什么样的设计模式,或者你在不经意间就已经用了设计模式当中的一种.本文旨在总结平时相对来说用的比较多的设计模式. 回到顶部 什么是设计模式 百度百科: 设计模式(Design pattern)是一套被反复使用.多数人知晓的.经过分类编目的.代码设计经验的总结. 使用设计模式是

javascript设计模式实践之迭代器--具有百叶窗切换图片效果的JQuery插件(一)

类似于幻灯片的切换效果,有时需要在网页中完成一些图片的自动切换效果,比如广告,宣传,产品介绍之类的,那么单纯的切就没意思了,需要在切换的时候通过一些效果使得切换生动些. 比较常用之一的就是窗帘切换了. 先贴上完成的效果. 实现原理不复杂,在动的一条一条的称之为“窗帘条”或者是“strip”,每一个strip都是一个div,类似于雪碧图的方式将其背景图的位置设置为strip的可视位置,然后用jquery的animate让他们按照一定规律动起来就完成窗帘切换效果了. 为了使用方便,将这个功能作为jq

Javascript设计模式系列三

继承,一个类或对象继承另一个类或对象的三种方法.类式继承.原型式继承.掺元类. 一.类式继承,原型链.Extend函数. <script type="text/javascript"> ////定义Person类 var Person = function (name) { this.name = name; }; Person.prototype.getName = function () { return this.name; }; ////原型链 function A

Javascript设计模式系列二

创建对象的基本模式,一.门户大开型,二.采用下划线来表示属性和方法的私用性,三.使用闭包来创建私用的成员. 一.门户大开型.只能提供公用成员.所有属性和方法都公开的.可访问的.这些共用属性都要使用this关键字来创建. <script type="text/javascript"> ////定义Dog对象 var Dog = function (name, age) { this.name = name; this.age = age; } Dog.prototype.Sa

《Javascript 设计模式》-读书笔记

第七章   设计模式类别 一.设计模式有三种类别 1.创建型模式:专注于处理对象机制.包括:构造器.工厂.抽象.原型.单例.生成器 2.结构型模式:用于找出在不同对象之间建立关系密切的简单方法. 包括:装饰者.外观.享元.适配器.代理 3.行为模式:用于改善或简化系统中不同对象之间的通信.包括:迭代器.中介者.观察者.访问者 第八章   设计模式分类 <Javascript 设计模式>-读书笔记,布布扣,bubuko.com

【读书笔记】读《JavaScript设计模式》之观察者模式

一.定义 在事件驱动的环境中,比如浏览器这种持续寻求用户关注的环境中,观察者模式(又名发布者-订阅者(publisher-subscripber)模式)是一种管理人与其任务之间的关系(确切地讲,是对象及其行为和状态之间的关系)的得力工具.用JavaScript的话来说,这种模式的实质就是你可以对程序中某个对象的状态进行观察,并且在其发生改变时能够得到通知. 二.例子 我们需要一个发布者的构造函数,它为该实例定义了一个类型为数组的属性,用来保存订阅者的引用. function Publisher(

方法的链式调用【参考javascript设计模式第6章】

对应经常使用jquery的朋友,方法的链式调用应该是已经很属性了,书上有模拟出一个很简单的类库代码, 见代码如下: Function.prototype.method = function(name,fn){ this.prototype[name] = fn; return this; }; (function(){ function _$(els){ ........ } /*Events  addEvent getEvent*/ _$.method("addEvent",func