假设有个需求,创建一个book类,有isbn码,书名,作者 ;可以对isbn进行数据完整性校验;--js设计模式

<script type="text/javascript">

/**
方案一,属性全部属于公有类型,用this创建
该方式可以在构造器中对数据的完整性进行检验的控制,但对其他人员会把什么值赋给该属性而不能进行数据完整性检验的控制;
**/

var Book = function(isbn,name,author){
  if(!this.checkIsbn(isbn)) throw new Error("不合法的isbn码");
  this.isbn = isbn;
  this.name = name || '没有名字';
  this.author = author || '没有作者';
}

 

Book.prototype={
  checkIsbn:function(isbn){
    /**
    专门用来检验isbn的数据完整性,以防在该类中其他方法中出错
    **/
    if(isbn||typeof isbn !='string'){
      return false;
    }
  // 可以对isbn进行各种校验  ...............
},
display:function(){
  /** 展示书本的一些信息 用this.isbn,this.name展示信息**/
  }
}

/** 优化后的方案一,以后所有的访问采用接口方式访问,属性用存取器来访问(可以将每个属性设置 为取值器和设置器(get,set);通过设置器你可以对你的属性(isbn)在存取器中进行数据完整性校验);
但是这种访问并不是强制性的,得靠开发人员自觉遵守,还是可以直接修改属性的;**/
var BookInter = new Interface('BookInter',['getIsbn','setIsbn','getName','setName','getAuthor','setAuthor','display']);
var Book = function(isbn,name,author){
  this.setIsbn(isbn);//采用存取器来设置属性
  this.setName(name);
  this.setAuthor(author);
 }
Book.prototype = {
  checkIsbn:function(isbn){
    ........
  },
  getIsbn:function(){
    return this.isbn;
  },
  setIsbn:function(isbn){
    if(!this.checkIsbn(isbn))throw new Error("不合法的isbn码");
    this.isbn = isbn;
  },
  getName:function(){
    return this.name;
  },
  setName:function(){
    this.name = name || '没有名字';
  },
  getAuthor:function(){
    return this.author
  },
  setAuthor:function(){
    this.author = author || '没有作者';
  },
  display:function(){
    //..................
  }
};

/**
方案二,采用闭包的方式形成真真的私有属性和方法;javascript中的作用域是词法性的;函数运行在定义他们的作用域中,而不是
运行在调用他们的作用域中。子类不能访问父类的所有私有属性和方法。所以用闭包实现私用成员导致了‘继承破坏封装’;有子类的话尽量用
方案一
**/
var Book = function(newIsbn,newName,newAuthor){
  var isbn,name,author;//私有属性
  function checkIsbn(isbn){
    //私有访法
  }
  //有特权的方法(那些需要直接访问私有成员的方法才被设置为特权方法,特权方法太多占用内存,每个对象实例都包含了所有特权方法的副本)
  this.getIsbn = function(){
    return isbn;
  };
  this.setIsbn = function(){
    if(!checkIsbn(newIsbn)) throw new Error('非法的isbn码');
    isbn = newIsbn;
  };
  this.getName = function(){
    return name;
  }
  this.setName = function(newName){
    name = newName || '没有名字';
  }
  this.getAuthor = function(){
    return author;
  }
  this.setAuthor = function(newAuthor){
    author = newAuthor || '没有作者';
  }

  //构造器代码
  this.setIsbn(newIsbn);
  this.setName(newName);
  this.setAuthor(newAuthor);
};
//公有的
Book.prototype = {
  display: function(){//不需要直接访问私有属性,可以通过特权方法来访问
    /**展示书刊的一些信息**/
  }
}

/**
方案三,可以在方案二的基础上给类和对象添加静态变量和方法(私有的和公有的),大多数方法,属性关联在类的实例(对象)上;静态的变量和方法关联在类对象(js处处是对象)上,静态成员都只有一份;
**/

var Book = (function(){//在这里,book想当于是一个构造函数,return返回这个函数, 括号括起来的相当于是个闭包;
  //静态变量(私)
  var countBookNum=0;
  //静态方法(私)
  function checkIsbn(isbn){
    if(!isbn||typeof isbn !='string'){
    return false;
  }
  return true;
}
//返回构造函数(作为一个内嵌函数返回)
return function(newIsbn,newName,newAuthor){
  var isbn,name,author;//私有属性
  //有特权的方法(那些需要直接访问私有成员的方法才被设置为特权方法,特权方法太多占用内存,每个对象实例都包含了所有特权方法的复本)
  this.getIsbn = function(){
    return isbn;
  };
  this.setIsbn = function(){
    if(!checkIsbn(newIsbn)) throw new Error('非法的isbn码');
    isbn = newIsbn;
  };
  this.getName = function(){
    return name;
  }
  this.setName = function(newName){
    name = newName || '没有名字';
  }
  this.getAuthor = function(){
    return author;
  }
  this.setAuthor = function(newAuthor){
    author = newAuthor || '没有作者';
  }
  countBookNum++;
  if(countBookNum>5) throw new Error("书本只能有"+(countBookNum-1)+"本!");
  //构造器代码
  this.setIsbn(newIsbn);
  this.setName(newName);
  this.setAuthor(newAuthor);
}
})();
/**该方法作为构造函数的属性出现的;是公有的,静态函数**/
Book.converteUpperCase = function(inputString){
  alert(inputString.toUpperCase());
}

Book.prototype = {
  display: function(){
    /**展示书刊的一些信息**/
    alert("** "+this.getIsbn()+" *** "+this.getName()+" ** "+this.getAuthor());
  }
}

/**代码测试:这里要进行异常处理**/
try{
  for(var i=0;i<7;i++){
    var b = new Book('12qw','极品药师','明明');
    b.display();
    b = null;
  }
}catch(e){
  alert(e);
}
Book.conterLitterCase('Hello World!');//静态公有方法的调用(实际是作为构造函数的属性)

</script>

注:方案三中私有成员和特权成员仍被申明在构造器中,构造器却变成一个内嵌函数,并作为包含它的函数的返回值赋给了Book。创建了一个闭包。位于外层函数申明的一对括号很重要,作用是代码一载入立即执行这个函数。这个函数返回值是另一个函数,被赋给了Book变量,因此Book成了一个构造函数;实例化Book时,调用的是这个内层函数。外层那个函数只是用于创建一个可以用来存放静态私用成员的闭包。

checkIsbn被设计为静态方法,是不让每个对象中都有一个这个函数;静态属性countBookNum统计Book构造器的总调用次数。

js两种生成对象模式(公有成员和成员私有)的更多相关文章

  1. 关于微软企业库中依赖注入容器Unity两种生成对象的实现u

    http://www.byywee.com/page/M0/S261/261037.html

  2. js两种定义函数、继承方式及区别

    一:js两种定义函数的方式及区别 1:函数声明: function sayA() { alert("i am A"); } 2:函数表达式: var sayB = function ...

  3. JavaScript中的两种全局对象

    这里总结的东西特别适合先学习c/c++, Java这类标准语言再学JS的童鞋们看,因为JS在程序执行之前就会初始化一个全局对象,这个全局对象到底是什么是跟JS程序运行环境有关的. 根据JavaScri ...

  4. 原生Js 两种方法实现页面关键字高亮显示

    原生Js 两种方法实现页面关键字高亮显示 上网看了看别人写的,不是兼容问题就是代码繁琐,自己琢磨了一下用两种方法都可以实现,各有利弊. 方法一 依靠正则表达式修改 1.获取obj的html2.统一替换 ...

  5. GitHub Flow & Git Flow 基于Git 的两种协作开发模式

    介绍基于Git 两种协作开发模式,GitHub Flow & Git Flow 对于Github 一些好用的特殊操作技巧 ,可以见GitHub 特殊操作技巧 和Git的基本操作 一 GitHu ...

  6. 死磕Spring之AOP篇 - Spring AOP两种代理对象的拦截处理

    该系列文章是本人在学习 Spring 的过程中总结下来的,里面涉及到相关源码,可能对读者不太友好,请结合我的源码注释 Spring 源码分析 GitHub 地址 进行阅读. Spring 版本:5.1 ...

  7. iframe-父子-兄弟页面相互传值(jq和js两种方法)

    参考文章: http://blog.csdn.net/u013299635/article/details/78773207 http://www.cnblogs.com/xyicheng/archi ...

  8. 原生js - 两种图片懒加载实现原理

    目前图片懒加载的方式主要有两种: 1.利用getBoundingClientRectAPI得到当前元素与视窗的距离来判断 2.利用h5的新API IntersectionObserver 来实现 ge ...

  9. 两种交换机配置模式,以配置基于端口划分的VLAN为例

    关于交换机的配置模式,大体上可以分为两类:其一以CISCO交换机为代表的配置模式,其二以Huawei.H3C交换机为代表的配置模式.其实这两种配置模式并没有本质的不同,只是配置的命令名称和配置方式存在 ...

随机推荐

  1. greenlet微线程

    Greenlet简介 一个 “greenlet” 是一个很小的独立微线程.可以把它想像成一个堆栈帧,栈底是初始调用,而栈顶是当前greenlet的暂停位置.你使用greenlet创建一堆这样的堆 栈, ...

  2. pearl(二分查找,stl)

    最近大概把有关二分的题目都看了一遍... 嗯..这题是二分查找...二分查找的代码都类似,所以打起来会水很多 但是刚开始打二分还是很容易写挂..所以依旧需要注意 题2 天堂的珍珠 [题目描述] 我有很 ...

  3. ASP.NET MVC实现剪切板功能

    前言 关于复制粘贴的功能,好像不用劳师动众的写后端代码,JS就可以,但正如大家所知道的,兼容性问题,当然这么通用的功能怎么可能没有一个通用的方案呢,于是便找到了一款jquery插件 jquery.cl ...

  4. C/C++基础知识总结——函数

    1. 随机函数的使用 1.1 头文件: # include <cstdlib> 或 # include <stdlib.h> 1.2 用法 srand(int seed);// ...

  5. Cocos2d学习之路三(使用Zwoptex创建精灵表单和CCAnimate动画)

    创建精灵表单: 创建动画先要把图片整合到一个图片上然后生成plist文件: 方法下载Zwoptex软件:http://www.zwopple.com/zwoptex/ 然后打开选择 create ne ...

  6. HTML5 实现拍照上传

    最近开始研究Html5,感觉功能很强大,下面做个实现拍照上传功能的例子. 一.视图:注意,在不同的浏览器有不同的navigator格式,其他类型浏览器的格式大家可以直接网上找到,这里就不列举了 < ...

  7. JS的基本概念

    JS的基本概念 任何语言的核心都必然会描述这门语言最基本的工作原理.而描述的内容通常都要涉及这门语言的语法,操作符,数据类型,内置功能等用于构建复杂解决方案的概念.Ecma-262通过叫做EcmaSc ...

  8. 网络爬虫的C++程序

    [搜片神器]之DHT网络爬虫的C++程序初步开源 回应大家的要求,特地整理了一开始自己整合的代码,这样最简单,最直接的可以分析流程,至于文章里面提供的程序界面更多,需要大家自己开发. 谢谢园子朋友的支 ...

  9. 数据访问模式之Repository模式

    数据访问模式之Repository模式   数据访问层无非就是对数据进行增删改查,其中增.删.改等我们可以抽象出来写一个公共的接口或抽象类来定义这些方法,并采用一个基类实现这些方法,这样该基类派生的子 ...

  10. SSH使用技巧

    SSH使用技巧 SSH免输入密码 原理是依赖证书去认证,从而免除密码输入. 通过ssh-keygen生成一对公私钥,是否使用passphrase可以根据个人喜好.(其实使用证书就是为了方便而已,我是不 ...