01单例模式

首先看一个问题,我们要在程序中描述两个人,这两个人都有姓名和年龄,可能刚刚开始学习js的时候会写成这样:

 var name1 = 'iceman';
var age1 = 25; var name2 = 'mengzhe';
var age2 = 26;

以上的写法的确是描述两个人,每个人都有姓名和年龄,但是每个人的姓名和年龄并没有放在一起,也就是说每个人的年龄和姓名并没有对应起来。这时候我们就引出对象的概念:把描述同一个事物(同一个对象)的属性和方法放在同一个内存空间下面,起到了分组的作用,这样不同事物之间的属性即使属性名相同相互也不会发生冲突。

 var person1 = {
name:'iceman',
age:25}; var person2 = {
name:'mengzhe',
age:26};

以上这种写法可以认为是一种分组编写代码的模式,通过如此分组之后,每一个人的姓名和年龄都在同一块内存空间下,也就是每个人的姓名和年龄都对应起来了。我们也把这种分组编写代码的模式称之为单例模式(在《JavaScript高级程序设计》中也称之为对象字面量模式),在单例模式中,把person1和person2叫做命名空间。

单例模式是一种项目开发中经常使用的模式,因为项目中我们可以使用单例模式来进行模块化开发,对一个相对来说比较大的项目中,需要多人协作开发,所以一般情况下会根据当前项目的需求,划分几个功能模块,每个人负责一部分,同时开发,最后把每个人的代码进行合并,比如:

公共模块:提供公共方法

 var utils = {
select:function () {
//...
}
};

页面选项卡模块:实现选项卡切换

 var tabModule = {
change:function () {
utils.select(); // 在自己的命名空间下调用其他命名空间的方法
}
};

搜索模块:实现搜索内容变化的处理

 var searchModule  = {
change:function () {
this.clickEvent(); // 在自己的命名空间下调用自己命名空间的方法
},
clickEvent:function () {
//...
}
};

以上在例子中,在选项卡模块(tabModule)和和搜索模块(searchModule)中都有change方法,如果没有分模块来编写的话会造成命名的冲突,按照JavaScript语言的解析规则,后声明的方法会覆盖前面声明的方法。而通过模块划分之后,这两个模块下的change方法归属于各自的模块,调用的时候都是调用自己模块下的方法(tabModule.change()、searchModule.change()),不会有冲突。

02工厂模式

回顾单例模式:
 var person1 = {
name:'iceman',
age:25,
writeJs:function () {
console.log(this.name + 'write js');
}
};
person1.writeJs();

单例模式解决了分组的问题,让每个对象有了自己独立的命名空间,但是不能批量生产,每一个新的对象都要重新写一份一模一样的代码。这时候就有了工厂模式,即:把实现同一事情的相同代码,放到一个函数中,以后如果再想实现这个功能,就不需要重新编写这些代码了,只要执行当前的函数即可,这就是函数的封装,体现了高内聚、低耦合的思想:减少页面的中的冗余代码,提高代码的重复利用率:

 function createPerson(name, age) {
var obj = {};
obj.name = name;
obj.age = age;
obj.writeJs = function () {
console.log(this.name + 'write js');
} return obj;
} var p1 = createPerson('mengzhe' , 26);
p1.writeJs(); var p2 = createPerson('iceman' , 25);
p2.writeJs();

顺便讲一下重载:在Java、C#等强类型的面向对象编程语言中,有函数重载的概念,但是在JavaScript中不存在重载,如果方法名一样的话,后面的会把前面的覆盖掉,最后只保留一个方法的定义,不过我们可以根据传递的参数不一样,实现模拟重载的功能:

 function sum(num) {    if (typeof num === 'undefined') {        return 0;
} return num;
}
sum(100);
sum();

03构造函数模式

 function CreateJsPerson(name, age) {
this.name = name;
this.age = age;
this.writeJs = function () {
console.log(this.name + 'write js');
}
// 浏览器再把创建的实例默认的进行返回
}
var p1 = new CreateJsPerson('iceman' , 25);
p1.writeJs();
var p2 = new CreateJsPerson('mengzhe' , 26);
p2.writeJs();

注意:上面是new CreateJsPerson('iceman' , 25)这样,使用了new创建了对象,这和普通调用函数的方式有区别的:

 var res = CreateJsPerson('xx' , 7);

这样没有用new而直接调用函数的方式,不是构造函数而是普通函数执行,由于没有写return,所以res=undefined,并且CreateJsPerson这个方法中的this是window。

构造函数模式的目的就是为了创建一个自定义类,并且创建这个类的实例。

构造函数模式和普通函数的模式的区别:

执行的时候

  • 普通函数执行:CreateJsPerson()

  • 构造函数执行:new CreateJsPerson(),通过new执行后,CreateJsPerson就是一个类了,而函数的返回值就是CreateJsPerson这个类的一个实例。

在函数代码执行的时候

  • 相同:都是形成一个私有的作用域,然后经历:形参赋值 --> 预解释 --> 代码从上到下执行(类和普通的函数一样执行,它也有普通函数的一面)。

  • 不同:① 在构造函数的代码执行之前,不用自己再手动的创建对象,浏览器会默认的创建一个对象数据类型的值(这个对象类型的值其实就是当前类的一个实例);② 接下来代码从上到下执行,以当前实例为执行的主体(this代表的就是当前的实例),然后分别的把属性名和属性值赋值给当前的实例;③ 最后,浏览器会默认的把创建的实例返回。

注意点:

  • JavaScript中所有的类都是函数数据类型的,它通过new执行变成了一个类,但是它本身也是一个普通的函数;

  • JavaScript中所有的实例都是对象数据类型的;

  • 在构造函数模式中,类中(函数体中)出现的 this.xx = xx中的this是当前类的一个实例;

  • p1和p2都是CreatePerson这个类的实例,所以都拥有writeJs这个方法,但是不同实例之间的方法是不一样的,在类中给实例增加的属性(this.xxx=xxx)属于当前实例的私有的属性,实例和实例之间是单独的个体,所以私有的属性之间是不相等的。

     console.log(p1.writeJs === p2.writeJs); // --> false

JavaScript 创建对象之单例、工厂、构造函数模式的更多相关文章

  1. php : MVC 演示(使用单例工厂)

    此例子是MVC的简单应用, 要达到的效果如下: 用户列表: 姓名 年龄 学历 兴趣 出生地 账号创建时间 操作 keen 20 高中 篮球,足球 广东 2016-11-08 10:00:31 删除 a ...

  2. Redis 单例、主从模式、sentinel 以及集群的配置方式及优缺点对比(转)

    摘要: redis作为一种NoSql数据库,其提供了一种高效的缓存方案,本文则主要对其单例,主从模式,sentinel以及集群的配置方式进行说明,对比其优缺点,阐述redis作为一种缓存框架的高可用性 ...

  3. 如何将业务代码写得像诗一样(使用注解+单例+工厂去掉一大波if和else判断)

    1.订单控制器,提供一个根据商品id和银行渠道id计算商品折后价格的接口: import org.springframework.web.bind.annotation.GetMapping; imp ...

  4. JavaScript构造函数+原型创建对象,原型链+借用构造函数模式继承父类练习

    虽然经常说是做前端开发的,但常常使用的技术反而是JQuery比较多一点.在JavaScript的使用上相对而言少些.尤其是在创建对象使用原型链继承上面,在项目开发中很少用到.所以今天做个demo练习一 ...

  5. PHP设计模式之工厂/单例/注册者模式

    工厂模式 简单工厂模式 [静态工厂方法模式](Static Factory Method)是类的创建模式 工厂模式的几种形态: 1.简单工厂模式(Simple Factory)又叫做 静态工厂方法模式 ...

  6. JavaScript之面向对象学习六原型模式创建对象的问题,组合使用构造函数模式和原型模式创建对象

    一.仔细分析前面的原型模式创建对象的方法,发现原型模式创建对象,也存在一些问题,如下: 1.它省略了为构造函数传递初始化参数这个环节,结果所有实例在默认的情况下都将取得相同的属性值,这还不是最大的问题 ...

  7. Swift百万线程攻破单例(Singleton)模式

    一.不安全的单例实现 在上一篇文章我们给出了单例的设计模式,直接给出了线程安全的实现方法.单例的实现有多种方法,如下面: class SwiftSingleton { class var shared ...

  8. Redis单例、主从模式、sentinel以及集群的配置方式及优缺点对比

    https://my.oschina.net/zhangxufeng/blog/905611

  9. 适配器、工厂模式、线程池、线程组、互斥锁、Timer类、Runtime类、单例设计模式(二十四)

    1.多线程方法 * Thread 里面的俩个方法* 1.yield让出CPU,又称为礼让线程* 2.setPriority()设置线程的优先级 * 优先级最大是10,Thread.MAX_PRIORI ...

随机推荐

  1. 今天写了一个简单的新浪新闻RSS操作类库

    今天,有位群友问我如何获新浪新闻列表相关问题,我想,用正则表达式网页中取显然既复杂又不一定准确,现在许多大型网站都有RSS集合,所以我就跟他说用RSS应该好办一些. 一年前我写过一个RSS阅读器,不过 ...

  2. python爬虫03:那个叫做 Urllib 的库让我们的 python 假装是浏览器

    相信你已经摸清了 浏览器各种请求的套路 也知道了怎么在手机上进行请求和返回数据的抓取 那么接下来我们就开始来使用 python 了 代码 lu 起来 那么 怎么用 python 写各种请求呢? 今天要 ...

  3. SOA案例架构分析浅谈

    上课中讲到了SOA架构设计,自己在课下决定总结一下对于SOA架构的理解以及应用. 先总结一下SOA的定义,SOA是面向服务架构,它可以根据需求通过网络对松散耦合的粗粒度应用组件进行分布式部署.组合和使 ...

  4. Spring Cloud Sleuth(十四)

    作用 再微服务中 服务调用服务很常见.服务中相互调用链路追踪的尤为重要,能够帮助我们再异常时分析出哪个服务出了异常.以及各个链路中相互调用所消耗时间,通过这些数据能够帮助我们分析出各个服务的性能瓶颈 ...

  5. Timus - 1213 - Cockroaches!

    先上题目: 1213. Cockroaches! Time limit: 1.0 secondMemory limit: 64 MB It's well-known that the most ten ...

  6. 链表快排 & 基于链表的排序

    以前只知道链表做插入(朴素.非二分)排序挺方便的.现在知道了(单)链表进行快速排序也是很好的(只是跟一般的快排的方式不一样). 参考: http://blog.csdn.net/otuhacker/a ...

  7. REST当道,NO MVC

    前世今生 B/S开发经历了几个时代,如今已经是后MVC时期了. MVC体现了分层和解耦合的概念.从功能和理念上都做出过巨大贡献,使Java B/S开发在面对大型项目时从容不迫,说成是上个十年Java ...

  8. 《编程导论(Java)·1.4.1 范式》

    这个楼主,是我的学生么?2013年写的! 嗯."编程范式或许是学习不论什么一门编程语言时要理解的最重要的术语".这句话早在2005年出版<Java程序设计>(宋中山,严 ...

  9. hdu 1698 Just a Hook 基本线段树

    使用线段树更新每段区间的奖(1,2,3),最后在统计整段区间的数和,基本线段树,果断1A啊 #include<iostream> #include<stdio.h> using ...

  10. C语言之基本算法41—字符串匹配问题

    //字符串匹配问题 /* =============================================================== 题目:输入两字符串S,T,输出在S中存在但在T ...