javaScript常用设计模式

一:理解工厂模式
案例:

function CreatePerson(name,age,sex) {
    var obj = new Object();
    obj.name = name;
    obj.age = age;
    obj.sex = sex;
    obj.sayName = function(){
        return this.name;
    }
    return obj;
}
var p1 = new CreatePerson("longen",'28','男');
var p2 = new CreatePerson("tugenhua",'27','女');
console.log(p1.name); // longen
console.log(p1.age);  // 28
console.log(p1.sex);  // 男
console.log(p1.sayName()); // longen
 
console.log(p2.name);  // tugenhua
console.log(p2.age);   // 27
console.log(p2.sex);   // 女
console.log(p2.sayName()); // tugenhua
 
// 返回都是object 无法识别对象的类型 不知道他们是哪个对象的实列
console.log(typeof p1);  // object
console.log(typeof p2);  // object
console.log(p1 instanceof Object); // true

工厂模式是为了解决多个类似对象声明的问题;也就是为了解决实列化对象产生重复的问题。
但是没有结解决对象识别的问题

二.构造函数模式
既解决了重复实例化的问题,又解决了对象识别的问题
案例:

 function Person(name,age,job){

    this.name = name;

    this.age = age;

    this.job = job;

    this.sayName = function(){

      alert(this.name);

    }

  }

  var person1 = new Person("Nicholas", 29, "Software Engineer"); 

  var person2 = new Person('Grey',27,'Doctor');

Person()中的代码除了与第一个工厂模式的 createPerson()中相同的部分外,还存在以下不同之处:
 1.没有显式地创建对象;
 2. 直接将属性和方法赋给了 this 对象;
 3. 没有 return 语句。
 按照惯例,构造函数始终都应该以一个大写字母开头,而非构造函数则应该以一个小写字母开头。
 要创建 Person 的新实例,必须使用 new 操作符。以这种方式调用构造函数实际上会经历以下 4个步骤:
  (1) 创建一个新对象;
  (2) 将构造函数的作用域赋给新对象(因此 this 就指向了这个新对象);
  (3) 执行构造函数中的代码(为这个新对象添加属性);
  (4) 返回新对象。
  在前面例子的最后,person1 和 person2 分别保存着 Person 的一个不同的实例。这两个对象都有一个 constructor(构造函数)属性,该属性指向 Person,如下所示。
    alert(person1.constructor == Person); //true
    alert(person2.constructor == Person); //true
  对象的 constructor 属性最初是用来标识对象类型的。但是,提到检测对象类型,还是 instanceof 操作符要更可靠一些。我们在这个例子中创建的所有对象既是 Object 的实例,同时也是 Person的实例,这一点通过 instanceof 操作符可以得到验证。
    alert(person1 instanceof Object); //true
    alert(person1 instanceof Person); //true
    alert(person2 instanceof Object); //true
    alert(person2 instanceof Person); //true
  创建自定义的构造函数意味着将来可以将它的实例标识为一种特定的类型;而这正是构造函数模式胜过工厂模式的地方。
  在这个例子中,person1 和 person2 之所以同时是 Object 的实例,是因为所有对象均继承自 Object.
  前面例子中定义的 Person()函数可以通过下列任何一种方式来调用。
    // 当作构造函数使用
    var person = new Person(“Nicholas”, 29, “Software Engineer”);
    person.sayName(); //“Nicholas”
    // 作为普通函数调用
    Person(“Greg”, 27, “Doctor”); // 添加到 window
    window.sayName(); //“Greg”
    // 在另一个对象的作用域中调用
    var o = new Object();
    Person.call(o, “Kristen”, 25, “Nurse”);
    o.sayName(); //“Kristen”

这个例子中的前两行代码展示了构造函数的典型用法,即使用 new 操作符来创建一个新对象。
  接下来的两行代码展示了不使用new操作符调用Person()会出现什么结果:属性和方法都被添加给window对象了。
  当在全局作用域中调用一个函数时,this 对象总是指向 Global 对象(在浏览器中就是 window 对象)。
  因此,在调用完函数之后,可以通过 window 对象来调用 sayName()方法,并且还返回了"Greg"。最后,也可以使用 call()(或者 apply())在某个特殊对象的作用域中调用Person()函数。这里是在对象o 的作用域中调用的,因此调用后o 就拥有了所有属性和sayName()方法。
优点:没有显示的创建对象,没有返回语句,直接将属性赋给this对象,将Person的实例对象标识为一种特定的类型
缺点:每个方法在每个实例上面都需要重新定义一遍,

三.原型模式
原型链模式开发会导致不同的对象之间数据共享
案例:

function person() {

    }
    person.prototype.sleep = function () {
        return "睡觉";
    }
    person.prototype.name = "张三";
    var p = new person();
    console.log(p);
    var p1 = new person();
    console.log(p1);

注意:省略了为构造函数传递初始化参数,结果所有实例享有相同的属性(对于函数实用,但是对于那些基本属性也说的过去,但是对于引用类型的数据就麻烦了)
基本属性我们可以在实例当中添加一个同名属性,这样可以隐藏原型当中的对应的属性,但是引用类型的属性却会导致所有实例共享

四.组合构造模式 + 原型链模式
构造函数用于定义实例属性,原型上面定义共享的属性和方法
案例:

function f1() {
        this.name = "毛豆"
    }
    f1.prototype.sleep = function () {
        return "睡觉"
    }
    var f = new f1();
    console.log(f);

五.单例模式
限制类的实例化次数只能是一次。
如果该实例不存在的情况下,可以通过一个方法创建一个类来实现创建类的新实例,如果实例已经存在,它会简单返回该对象的引用。
案例:

var obj = (function () {
        var newobj;

        function getobj() {
            //实例化对象  返回对象
            if (newobj == undefined) {
                newobj = new factory();
            }
            return newobj;
        }

        //创建对象的实例
        function factory() {
            //对象的封装
            this.name = "";
            this.sex = "";
            this.sleep = function () {

            }
        }

        return {
            getObj: getobj
        }
    })();
    console.log(obj.getObj());

适用场景
1.需要频繁实例化然后销毁的对象。
2.频繁访问数据库或文件的对象。
3.创建对象时耗时过多或者耗资源过多,但又经常用到的对象。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值