<1>工厂模式
简单来说就是封装后的代码,简单的工厂模式是很好理解的,关于它的作用,就是利用面向对象的方法,把一些对象封装,使一些占用空间多的,重复的代码封装起来。实现方法非常简单,也就是在函数内创建一个对象,给对象赋予属性以及方法再将对象返回即可。
function creatper(name,age){
var per=new Object(); //原料
//加工
per.name=name;
per.age=age;
per.sayHi=function(){
console.log(per.name+''+per.age); }
return per; //出厂
}
var me=creatper('katherine',22);
me.sayHi();
console.log(me.name);
可以看出,使用工厂模式,可以重复调用这个per函数来生成不同属性值得对象,这就像工厂一样,批量生产,里面的原料,加工,出厂都很清晰。但是你会发现工厂模式是无法识别对象的类型,因为全都是object,不像Date,Array等,但是构造函数就不是了。这还只是简单的工厂模式,复杂的工厂模式(抽象模式)等以后再回来详细了解。
<2>构造函数模式
ECMAScript中构造函数可以用来创建特定对象,类似于Array,Date等原生的js对象
function Student(name,age,classa){
this.name=name;
this.age=age;
this.classa=classa;
this.sayHello=function(){
console.log(this.name,this.age,this.classa);
}
}
var me=new Student("xiaoai",22,"大三");
console.log(me.classa);
me.sayHello();
console.log(me instanceof Student);//true
由代码可以看出,于工厂模式除了函数名不同以外,还要注意:构造函数名的首字母大写(不过好像没有严格规定)。构造函数也没有显示创建的对象,使用了this,直接把属性和方法赋值给了this对象。没有return语句,实例化的时候要使用new,而且它能够识别对象(这正是构造函数模式胜于工厂模式的地方)。
构造函数虽然好用,但也有很大的缺点,就是每次创建实例的时候都要重新创建一次方法,实际应用中,每次创建对象的时候属性值不同,而对象的方法却是相同的,所以创建两次完全相同的方法是没有必要的,因此有人会说可以把函数方法放到对象外面。如下:
function Student(name,age,classa){
this.name=name;
this.age=age;
this.classa=classa;
}
function sayHello(){
console.log(this.name,this.age,this.classa);
}
var me=new Student("xiaoai",22,"大三");
console.log(me.classa);
me.sayHello();
console.log(me instanceof Student);
这样一改,就把sayhello函数设置成了全局函数,这样一来Student的每一个实例访问的都是同一个函数,可是,在全局作用域中定义一个只供student使用的函数,就显得有些过分了,如果在全局作用域中定义许多这样仅供特定对象使用的方法,那就太浪费空间了,显然也失去了面向对象所注重的封装性了,因此完全可以使用原型解决这个问题。
<3>原型模式
js规定每一个创建的函数都有prototype(原型)属性,这个属性是指针,指向一个对象,而这个对象的用途是包含由特定类型的所有实例所共享的属性和方法,使用原型对象就可以让所有实例对象均包含这些属性及方法。
function per(){}
per.prototype.name='xiaoai';
per.prototype.age=22;
per.prototype.course=['php','javascript','java','C#'];
per.prototype.say=function(){
console.log(this.name+this.age+this.course);
}
var per1=new per();
var per2=new per();
per1.name='katherine';
per1.course.push('Html5');
per1.say();
per2.say();
per2.course.pop();
关于原型模式的缺点,我想也是很明显的,它省略了构造函数传递初始化参数这一环节,结果所有实例均在默认情况下取得了相同的属性值,虽然你可以在后来做出更改,但一点都不方便,这样还不是最大的问题,原型模式最大的问题是在于共享的本性所导致的,由于共享,因此一个实例修改了引用,另一个也随之更改了属性。因此一般不会单独使用原型模式。
<4>混合模式(原型模式+构造函数)
function per(name,age,course){
this.name=name;
this.age=age;
this.course=course;
}
per.prototype.say=function(){
console.log(this.name+this.age+this.course);
}
var per1=new per('katherine',22,['C#','java','PHP','Javascript']);
var per2=new per ('xiaoai',21,['oracle','mysql','nodejs','html5']);
per1.say();
per2.say();
per1.course.pop();
per1.say();
per2.say();
由代码可以看出混合模式的分工:构造函数用于定义实例的属性,而原型模式用于定义方法和一些共享的属性。每个实例都会有自己的属性,但同时又共享着方法,最大限度的节省了内存。另外这种模式还支持传递初始参数。使用最广泛。
<5>动态模式
function per(name,age,course){
this.name=name;
this.age=age;
this.course=course;
if(typeof this.say!='function'){
per.prototype.say=function(){
console.log(this.name+this.age+this.course);
}
}
}
var per1=new per('katherine',22,['C#','java','PHP','Javascript']);
var per2=new per('xiaoai',22,['oracle','mysql','nodejs','html5']);
per1.say();
per2.say();
per1.course.pop();
per1.say();
per2.say();