javascript面向对象——几种常见的设计模式 - Go语言中文社区

javascript面向对象——几种常见的设计模式


工厂模式:
这种模式比较简单,其实就是在函数中创建一个对象,给对象添加属性及其属性值或属性方法然后在讲这个对象用return返回出来。
如下面的实例:
function myfile(name,work){
    var myself = new Object();  //创建一个新的对象
    myself.name = name;
    myself.work = work;
    myself.sayWork = function(){
        alert(this.work);
    };
    return myself;  //返回这个新创建的对象
}
var myFile1 = myfile("zhang","IT");
myFile1.sayWork();
在这个例子中,我们在构造函数myfile中创建了一个新的对象,并为这个对象添加了属性及方法,在这个方法中this.work指向的则是调用它的对象,也就是myFile1,最后将新创建的这个对象用return返回出来,这样就能实现在外部调用。
那么如果我们不将新创建的对象返回出来会出现什么样的结果????如下图:

是的,这样会报错,我们并不能调用sayWork这个方法显示的是在原型对象中找不到sayWork这个方法。
构造函数模式:
构造函数模式相对于工厂模式要难以理解很多因为这种模式不仅创建了原型对象而且,它不像工厂模式创建的对象那么单一,只能是Object,构造函数模式创建特定类型的对象,如:Array、或Date等。
function Myfile(name,work){
    this.name = name;
    this.work = work;
    this.sayWork = function(){
        alert(this.work);
    };
};
var myFile1 = new Myfile("zhang","IT");
myFile1.sayWork();		//IT
alert(Myfile.prototype.isPrototypeOf(myFile1));	//true
//我们用isPrototypeOf属性来检查myfile的原型对象与实例化对象myFile1之间的关系。
这个是典型的构造函数模式,在我们创建了构造函数的同时原型对象也会随之创建出来,这个时候通过构造函数来创建的实例化对象也就会通过__proto__指向这个原型对象中。
总结:我们通过上面构造函数的实例简单的总结它的一下几个特点:
1、约定俗成,所有构造函数的函数名首字母需要大写,(当然也可以小写不会报错但是不好看)。
2、在构造函数中我们不需像工厂模式那样需要创建新的对象即 new Object();
3、在构造函数中我们是直接将属性以及方法赋值给了this对象,this指向的是调用它的那个对象。
4、当我们创建完成构造函数后需要new一个实例化的对象赋值给一个变量,然后可以通过这个变量来调用构造函数里面的属性以及方法。
原型模式:
function Myfile(){
    Myfile.prototype.name = "zhang";
    Myfile.prototype.work = "IT";
    Myfile.prototype.age = "100";
    Myfile.prototype.sex = "nan";
    Myfile.prototype.myself = function(){
        alert(this.name + this.work + this.age + this.sex);
    };
};
var myFile1 = new Myfile();
var myFile2 = new Myfile();
alert(myFile1.constructor == myFile2.constructor);
if((myFile1.name == myFile2.name) && (myFile1.work == myFile2.work) && (myFile1.age == myFile2.age) && (myFile1.sex == myFile2.sex)){
    alert("这两个实例化对象所引用了同一个原型对象.");
}else{
    alert("好吧,看来是我理解出错了!!!!");
}
我们看看弹出的结果是什么?如下图:
是的,正如图所示,我们创建的所有的构造函数都会有一个prototype(原型)属性,这个属性其实就是一个指针,它指向了一个对象,在这个对象里包含了可以共享给实例化对象的所有属性及方法。但是问题,我相信你应该也已经看出来了,由于原型模式中没有了构造函数模式中的this指向,在这里所有的属性都是固定写死的,也就是说上面创建的两个实例化的对象都是指向同一个原型对象中,而且原型对象的活动性很差,如果想修改其中一个实例化对象的属性或方法另一个实例对象也会随改变,这并非我们想要的结果,所以就会诞生了混合模式。
混合模式(构造函数模式 + 原型模式):
混合模式其实就是构造函数模式与原型模式的混合结果。
实例代码如下:
function myfile(name,work,friend){
this.name = name;
this.work = work;
this.friend = friend;
};
myfile.prototype.showMySelf = function(){
alert(this.name + this.work + this.friend);
};
var myself = new myfile("zhang","IT",["hu","li","he"]);
var myself2 = new myfile("hu","teacher",["he","yi","li"]);
myself.showMySelf();
myself2.showMySelf();
由上图可以看出代码运行一切正常,那么这个混合模式具体是怎么实现的呢!?它的运行方式是怎样的呢!?
其实很简单,在混合模式中构造函数主要是用于定义实例的属性,而原型模式我们都知道应用原型模式的时候会创建出原形对象,而这个对象正是用于储存原型模式定义的方法和共享的一些属性。
正如上面实例所示:实例化对象myself与myself2它们都共享着同一个方法,但是他们却都有属于自己的不同参数,从而传入构造函数的属性中去,在混合模式中每个实例化的对象既有共性,也有自己单独的部分,互不影响。
动态原型:
我们先看看下面这段代码,看看有什么不一样的地方。
function myfile(name, work) {
    this.name = name;
    this.work = work;

    if (typeof this.myInfo != 'function') {
        // 这段代码只执行了一次
        alert("这是正确的");
        myfile.prototype.myInfo = function() {
            alert(this.name + this.work);
        }
    }
}

var myself = new myfile('zhang', 'IT'),myself2 = new myfile('hu', 'teacher');
myself2.myInfo();
我们看看都弹出了一些什么,如下图:
这是上面代码输出的两个alert结果,重点是为什么我们这初始化了一个实例对象呢!myfile2并没有被初始化,但是myfile2.myInfo();依然能够正确显示。其实原因很简单,因为动态原型模式是将我们设置的所有信息全部封装在了构造函数中,然后通过构造函数来初始原型,其实我们只需要第一个对象实例化时初始化就行了,后面的实例化对象均可以不需要初始化。从上面代码弹出的结果我们就可以发现“这是正确的”其实也就只运行了一次,虽然我们做了两次实例化。
综上:我个人觉得还是混合模式(原型模式 + 构造函数模式)运用起来会比较好。
如有理解不当之处,欢迎各位老铁留言指正。谢谢!!!!

版权声明:本文来源CSDN,感谢博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明。
原文链接:https://blog.csdn.net/ZHJ145236/article/details/77645936
站方申明:本站部分内容来自社区用户分享,若涉及侵权,请联系站方删除。
  • 发表于 2020-03-01 22:50:46
  • 阅读 ( 1075 )
  • 分类:设计模式

0 条评论

请先 登录 后评论

官方社群

GO教程

猜你喜欢