JavaScript设计模式之一封装

发布于 2022-10-15 05:54:31 字数 7531 浏览 17 评论 0

JavaScript设计模式之一封装

对于熟悉C#和Java的兄弟们,面向对象的三大思想(封装,继承,多态)肯定是了解的,今天我想讲讲如何在Javascript中利用封装这个特性,开讲!

我们会把现实中的一些事物抽象成一个Class并且把事物的属性(名词)作为Class的Property把事物的动作(动词)作为Class的methods。在面向对象的语言中(C#等)都会有一些关键字来修饰类或者属性(Private,public,protect),这些关键词描述了访问的权限,不多做解释。

我们来看看Javascript的易变的特性(我们还用上一次的例子):

  1. var Man = function (name, age) {             this.Name = name;             this.Age = age;       }      var Person = new Interface("Person", ["GetName", "GetAge"]);            Man.prototype = { GetName: function () { return this.Name; },            GetAge: function () { return this.Age; }        }           var Alan = new Man("Alan", 25);      alert(Alan.GetAge());    Alan.DisplayAll = function () { return "Name: "+this.GetName() + "; Age: " + this.GetAge() }   alert(Alan.DisplayAll());

复制代码我先创建了一个Class(Javascript的匿名方法)拥有2个公共的(public)的字段(本篇blog会详细讲解,继续往下看)和2个public的方法,我们创建了一个Instance--Alan,但是我可以为这个Instance动态的添加一个DisplayAll的方法,我想任何面向对象的语言是做不到这一点的,Javascript的灵活体现之一。

我们现在假设一个场景,如果有很多的程序员要用这段代码,由于Javascript的易变性,程序员就可以在实例化后改变Name的值,那初始化的动作就没有意义了:

  1. var Alan = new Man("Alan", 25);       Alan.Name = "Alice"; //悲剧了,我alert的时候变成Alice了       alert(Alan.GetName());

复制代码所以我们不能让外部的人去任意的修改这个字段,在Java或C#中我们只需要个这个字段改为Private,就万事OK了,但是Javascript没有这个关键词,那我们需要这么做呢,这就是这篇blog存在的意义

我们可以想下在C#除了设置Private之外我们还可以怎么做?我们可以设置Setter和Getter方法。

我们来修改下上面的代码:我们称方法一:

  1. var Person = new Interface("Person", ["SetName", "SetAge", "GetName", "GetAge"]);        var Man = function (name, age) {            this.SetAge(age);            this.SetName(name);        }        Man.prototype = {            SetName: function (name) { this.Name = name; },            SetAge: function (age) { this.Age = age; },            GetName: function () { return this.Name; },            GetAge: function () { return this.Age; }        }       var Alan = new Man("Alan", 25);       Alan.Name = "Alice"; //悲剧了,我alert的时候变成Alice了       Alan.SetAge(10);//悲剧,被别人把我的年龄给这么小       alert(Alan.GetName());       Alan.DisplayAll = function () { return "Name: "+this.GetName() + "; Age: " + this.GetAge() }       alert(Alan.DisplayAll());

复制代码我们发现貌似样子很像C#中的Setter和Getter,但是还是可以被外部修改。但是从约束上来看,貌似比上面的code要好看些,通过方法来设置初始值。但是问题还是没有解决,我们来看看下面一种方法:闭包

  1. //我需要解释一下,在Javascript中是通过This关键字来开发权限的(Public)。

复制代码在讲闭包之前,我们需要了解下闭包的本质: 在Javascript中,只有方法是有作用域的,如果在方法中声明的变量在外部是无法访问的,那Private的概念就出来了。

  1. var Person = new Interface("Person", ["SetName", "SetAge", "GetName", "GetAge"]);       var Man = function (newname, newage) {               var name, age;               this.SetName = function (newname) { name = newname; }               this.SetAge = function (newage) { age = newage; }               this.GetName = function () { return name; }               this.GetAge = function () { return age; }               this.SetAge(newage);               this.SetName(newname);            }       var Alan = new Man("Alan", 25);       Alan.name="Alice"; //现在name是private了,我是无法去修改的       Alan.SetAge(10); //悲剧,被别人把我的年龄给这么小      alert(Alan.GetAge());

复制代码现在私有的功能就实现了,我们只是用Var来代替了This而已。//我们把公共(Public)并且可以访问Private的方法称为特权方法,比如上面的this.SetName, this.SetAge.

如果我们的公共方法不涉及到访问Private的字段,那我们可以把他们放到Prototype中。//好处是多个实例的时候内存中也只有一分拷贝

  1. Man.prototype.DisplayAll = function () { return "Name: " + this.GetName() + "; Age: " + this.GetAge() }

复制代码哈哈~我们来看下稍微有点难度的东西:静态变量和方法

我们都是知道静态的东西属于类(Class),我们来修改下上面的代码:

  1. var Person = new Interface("Person", ["SetName", "SetAge", "GetName", "GetAge","GetCount"]);      var Man = (function () {          var count = 0;          return function (newname, newage) {              var name, age;              this.SetName = function (newname) { name = newname; }              this.SetAge = function (newage) { age = newage; }              this.GetName = function () { return name; }              this.GetAge = function () { return age; }              this.GetCount = function () { return count; }              this.SetAge(newage);              this.SetName(newname);              count++;          }      })();          Man.prototype.DisplayAll = function () { return "Name: " + this.GetName() + "; Age: " + this.GetAge() }          var Alan1 = new Man("Alan", 25);          var Alan2 = new Man("Alan", 25);     alert("There are "+Alan2.GetCount()+" instances of Man" );

复制代码不管我们是通过Alan1或Alan2去GetCount,结果都一样都是2. 这里count就是一个私有的静态变量。

至于为什么,不懂的可以回复我的Post,我相信大家都能看懂的~!

如需转发请注明原文出处:http://www.cnblogs.com/jsjrjcj/archive/2011/05/27/2059691.html

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

青萝楚歌 2022-10-22 05:54:31

学习了

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文