JavaScript设计模式——前奏(封装和信息隐藏)

时间:2022-09-06 08:46:53

前面一篇讲了js设计模式的前奏,包括接口的讲解..

三:封装和信息隐藏:

信息隐藏用来进行解耦,定义一些私有的数据和方法。

封装是用来实现信息隐藏的技术,通过闭包实现私有数据的定义和使用。

接口在这其中扮演的角色是:提供一份记载着可公众访问的方法的契约,它定义了两个对象间可以具有的关系。

接下来介绍一下创建对象的基本模式:

基本模式有3种:门户大开型、用下划线表示方法和属性的私用性、闭包创建私用成员

举个例子,你要创建一个Book类,别人会创建实例并使用。

    //Book(isbn,title,author)
var theHobbit = new Book('0-12-34-2654-2','the hobbit','xin');
theHobbit.display();

1.门户大开型:

所谓门户大开,即,用一个函数来做构造器,所有方法和属性都是公开的。

     //定义接口
var Publication = new Interface('Publication',['getIsbn','setIsbn','getTitle','setTitle','getAuthor','setAuthor','display']); //implements Publication
var Book = function(isbn, title, author){
this.setIsbn(isbn);
this.setTitle(title);
this.setAuthor(author);
}
Book.prototype = {
checkIsbn:function(isbn){
//.....检查isbn的格式是否规范
//.......
},
getIsbn:function(){
return this.isbn;
},
getTitle:function(){
return this.title;
},
getAuthor:function(){
return this.author;
},
setIsbn:function(isbn){
if(!this.checkIsbn(isbn)) throw new Error('Book: Invalid ISBN');
this.isbn = isbn;
},
setTitle:function(title){
this.title = title || "no title specified";
},
setAuthor:function(author){
this.author = author || "no author specified";
},
display:function(){
//..............
alert(this.getIsbn()+this.getTitle()+this.getAuthor())
}

这种方法看似很完善了,但是对于里面的属性还是可以进行修改的,isbn亦可能被赋值为一个无效值。

2.用一个函数来做构造器(用命名规范区别私用成员)

这个方法和上面的方法如出一辙,就是给私有成员加一个下划线。

就不做详细的讨论了。

3.作用域、嵌套和闭包

     //implements Publication
var Book = function(newisbn, newtitle, newauthor){
//私有成员
var isbn,title,author //私有方法
function checkIsbn(isbn){
//.....检查isbn的格式是否规范
//.......
} //特权方法
this.getIsbn(){
return isbn;
}
this.getTitle(){
return title;
}
this.getAuthor(){
return author;
}
this.setIsbn(){
if(!checkIsbn(newisbn)) throw new Error('Book: Invalid ISBN');
isbn = newisbn;
}
this.setTitle(){
title = newtitle;
}
this.setAuthor(){
author = newauthor;
} //构造
this.setIsbn(newisbn);
this.setAuthor(newauthor);
this.setTitle(newtitle);
} Book.prototype = {
display:function(){
//..............
}

这种方法存在一个问题。前面的门户大开型方法对象创建模式中,所有的方法都创建在原型对象上,因此不管生成多少对象实例,这些方法在内存中只会存在一份。而这种方法每次生成一个新的对象实例都会为每一个私用方法和特权方法生成一个新的副本。这种做法会浪费更多的内存。

这种对象创建模式不利于派生子类。(继承破坏封装.....)

最后总结一下:

私有属性和方法:函数有作用域,在函数内用var 关键字声明的变量在外部无法访问,私有属性和方法本质就是你希望在对象外部无法访问的变量。
特权属性和方法:创建属性和方法时使用的this关键字,因为这些方法定义在构造器的作用域中,所以它们可以访问到私有属性和方法;只有那些需要直接访问私有成员的方法才应该被设计为特权方法。
公有属性和方法:直接链在prototype上的属性和方法,不可以访问构造器内的私有成员,可以访问特权成员,子类会继承所有的共有方法。
公有静态属性和方法:最好的理解方式就是把它想象成一个命名空间,实际上相当于把构造器作为命名空间来使用。

     /* -- 封装 -- */
var classA =function(){
//私有属性和方法
var name ='Xin';
var method1 =function(){
//...
}
//特权属性和方法
this.age ='20' ;
this.getName =function(){
return name;
}
}
//共有静态属性和方法
classA._name ='Darren code';
classA.alertName =function(){
console.log(_name);
}
//共有属性和方法
classA.prototype = {
init:function(){
//.....
},
init2:function(){
//.....
}
}

四:继承:

1.类式继承  (组合继承)

     //超级类(父类)
function Persion(name){
this.name = name;
}
Persion.prototype.getName = function(){
return this.name;
} //(子类)
function Author(name, books){
Persion.call(this, name);//调用超类的构造函数,把name作为参数传过去
this.books = books;
}
Author.prototype = new Persion();//子类的原型指向超类的实例,同时就会拥有超类的原型所指向的内存所拥有的方法和属性。
Author.prototype.constructor = Author;//因为子类的原型对象等于超类的实例,所以prototype.constructor这个方法也等于超类构造函数,所以要重新指定constructor.
Author.prototype.getBooks = function(){
return this.books;
}

首先创建构造函数,然后创建子类,通过call(this,arguments)来调用构造函数。然后设置原型链,js没有extend, so........ 就用prototype 来做继承。关于原型,不理解就自己看书吧,基础......要扎实........

子类的prototype是一个实例,就会拥有父类的prototype 属性,然后通过父类的prototype来找这块内存中存在的方法或者属性。

为了简化类的声明,可以把派生子类的整个过程包装在一个extend的函数中。

     function extend(subClass,superClass){
var F = function(){};
F.prototype = superClass.prototype;
subClass.prototype = new F();
subClass.prototype.constructor = subClass;
}
但是,这样存在一个问题。就是同名函数会被复写,可以添加一个superclass属性来解决这个问题。
     function extend(subClass,superClass){
var F = function(){};
F.prototype = superClass.prototype;
subClass.prototype = new F();
subClass.prototype.constructor = subClass; subClass.superclass = superClass.prototype;//添加superclass属性
if(superClass.prototype.constructor == Object.prototype.constructor){
superClass.prototype.constructor = superClass;
}
} function Author(name, books){
Author.superclass.constructor.call(this, name);
this.books = books;
}
extend(Author, Persion);
Author.prototype.getBooks = function(){
return this.books;
}
有了superclass属性,子类便可定义跟父类重名的原型方法,使用其原有函数的逻辑。
     Author.prototype.getName = function(){
var name = Author.superclass.constructor.getName.call(this);
return name + ",Author of" + this.getBooks().join(',');
}

//类式继承用到了原型链....原型链不懂的自己研究去吧.....

2.原型式继承

     /* -- 原型式继承 -- */
//clone()函数用来创建新的类Person对象
var clone =function(obj){
var _f =function(){};
//这句是原型式继承最核心的地方,函数的原型对象为对象字面量
_f.prototype = obj;
returnnew _f;
}
//先声明一个对象字面量
var Person = {
name:'Darren',
getName:function(){
returnthis.name;
}
}
//不需要定义一个Person的子类,只要执行一次克隆即可
var Programmer = clone(Person);
//可以直接获得Person提供的默认值,也可以添加或者修改属性和方法
alert(Programmer.getName())
Programmer.name ='Darren2'
alert(Programmer.getName()) //声明子类,执行一次克隆即可
var Someone = clone(Programmer);

总结:

类式继承(组合继承):使用原型链继承共享的属性和方法,而通过借用构造函数(   call( _ , _ )   )继承实例属性.

原型式继承:可以在不必预先定义构造函数的情况下实现继承,其本质是执行对给定对象的浅复制。而复制得到的副本还可以得到进一步改造。

类式继承,子类的原型指向一个父类的实例;原型式继承,子类的原型指向了父类的一个对象字面量(浅复制)。(子类都可能对父类的属性和方法进行修改。)

原型式继承会更省内存:被克隆出来的对象都共享每个属性和方法的唯一一份实例。而类式继承创建的每一个对象在内存中都有自己的一套属性(和私用方法)的副本。

最后:掺元类........

JavaScript设计模式——前奏(封装和信息隐藏)的更多相关文章

  1. 如何封装JS ----》JS设计模式《------ 封装与信息隐藏

    1. 封装与 信息隐藏之间的关系 实质是同一个概念的两种表达,信息隐藏式目的,二封装是借以达到目的的技术方法.封装是对象内部的数据表现形式和实现细节,要想访问封装过额对象中的数据,只有使用自己定义的操 ...

  2. JS设计模式——3.封装与信息隐藏

    封装.信息隐藏与接口的关系 信息隐藏是目的,封装是手段. 接口提供了一份记载着可供公共访问的方法的契约.它定义了两个对象间可以具有的关系.只要接口不变,这个关系的双方都是可以替换的. 一个理想的软件系 ...

  3. JavaScript设计模式——前奏

    Function.prototype.method = function(name,fn){ this.prototype[name] = fn; } var Anim = function(){ / ...

  4. JavaScript设计模式-6.封装

    <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...

  5. JavaScript设计模式之一封装

    对于熟悉C#和Java的兄弟们,面向对象的三大思想(封装,继承,多态)肯定是了解的,今天我想讲讲如何在Javascript中利用封装这个特性,开讲! 我们会把现实中的一些事物抽象成一个Class并且把 ...

  6. 《JavaScript设计模式》笔记之第三章:封装和信息隐藏

    第三章 创建对象的基本模式 方法一:门户大开型 var Book = function(isbn, title, author) {   if(isbn == undefined ) throw ne ...

  7. 《javascript设计模式》读书笔记二(封装和隐藏信息)

    1.为什么要封装和信息隐藏 做过编程的朋友们知道"耦合"这个词.事实上封装的效果就是为了解耦,让类和类之间没有太多的联系,防止某一天改动某一类的时候,产生"多米骨诺牌效应 ...

  8. Javascript设计模式&lpar;1&rpar;

    本文是学习了<JavaScript设计模式>(谢廷晟 译)做的学习笔记 一.JavaScript的灵活性 1. 普通 functon function startAnimation() { ...

  9. Javascript设计模式笔记

    Javascript是越来越厉害了,一统前后端开发.于是最近把设计模式又看了一遍,顺便做了个笔记,以方便自己和他人共同学习. 笔记连载详见:http://www.meteorcn.net/wordpr ...

随机推荐

  1. 读过MBA的CEO更自私?《哈佛商业评论》2016年第12期。4星

    老牌管理杂志.每期都值得精度.本期我还是给4星. 以下是本书中的一些内容的摘抄: 1:他们发现在Airbnb上,如果客人姓名听起来像黑人,那么比名字像白人的客人的接受率会低16%.#45 2:对立组织 ...

  2. &lbrack;转&rsqb;Fiddler抓取Android真机上的HTTPS包

    此篇文章转载自:http://blog.csdn.net/roland_sun/article/details/30078353 工作中经常会需要对一些app进行抓包, 但是每次默认都是只抓http请 ...

  3. 2016-12-21&lpar;1&rpar;Git常用命令总结

    友情链接:http://www.cnblogs.com/mengdd/p/4153773.html

  4. Python Sqlite3以字典形式返回查询结果

    sqlite3本身并没有像pymysql一样原生提供字典形式的游标. cursor = conn.cursor(pymysql.cursors.DictCursor) 但官方文档里已经有预留了相应的实 ...

  5. OSG中的示例程序简介

    OSG中的示例程序简介 转自:http://www.cnblogs.com/indif/archive/2011/05/13/2045136.html 1.example_osganimate一)演示 ...

  6. 与(and)&amp&semi;&amp&semi;

    /与(and)&& var box = (5>3)&&(4>3); alert(box); //true 如果脸变的操作数有一个操作数不是boolean值得 ...

  7. Collection的toArray&lpar;&rpar;使用上需要注意的地方

    转载:http://llade.iteye.com/blog/199818 Collection在很多情况下需要转换为数组来处理(很多接口方法都使用array作为参数). Collection的toA ...

  8. Google地图

    Google地图开发总结 我们经常使用地图查位置.看公交.看街景,同时地图还开放第三方的API给开发者.利用这些API进行地图的个性化的展示和控制,例如北京被水淹了,开发一个网页显示北京被淹的地图,地 ...

  9. Ajax检测用户名是否已经注册

    程序功能 当用户名输入完成(即用户名输入框失去焦点),利用Ajax检测用户名是否已经注册! 实现过程 利用Ajax向CheckUserServlet发送请求,判断该用户名是否可用.这里只是为了演示Aj ...

  10. Anaconda入门安装教程

    Anaconda 是什么? Anaconda 是一个可用于科学计算的 Python 发行版,支持 Linux.Mac.Windows系统,内置了常用的科学计算包.它解决了官方 Python 的两大痛点 ...