Try again

200512270453934121.gif

博客园 首页 联系 管理

目标:

       回顾面向对象编程,了解 JavaScript 语言特性,选择可支持 OOP 思想的 JavaScript 框架。

 

关于面向对象:

三个非常基础的概念: “ 类与对象 ” 、 “ 继承与组合 ” 、 “ 虚函数与多态 ” 。

一、 类与对象

对象( Object )是类( Class )的一个实例( Instance )。如果将对象比作房子,那么类就是房子的设计图纸。所以面向对象程序设计的重点是类的设计,而不是对象的设计。类可以将数据和函数封装在一起,其中函数表示了类的行为(或称服务)。类提供关键字 public 、 protected 和 private 用于声明哪些数据和函数是公有的、受保护的或者是私有的。

这样可以达到信息隐藏的目的,即让类仅仅公开必须要让外界知道的内容,而隐藏其它一切内容。我们不可以滥用类的封装功能,不要把它当成火锅,什么东西都往里扔。

在设计类时“以行为为中心”,即首先考虑类应该提供什么样的函数。

设计孤立的类是比较容易的,难的是正确设计基类及其派生类。因为有些搞不清楚“继承”( Inheritance )、“组合”( Composition )、“多态”( Polymorphism )这些概念。

 

二、 继承与组合

“继承”特性可以提高程序的可复用性。正因为“继承”太有用、太容易用,才要防止乱用“继承”。我们要给“继承”立一些使用规则:

a 、如果类 A 和类 B 毫不相关,不可以为了使 B 的功能更多些而让 B 继承 A 的功能。不要觉得“不吃白不吃”,让一个好端端的健壮青年无缘无故地吃人参补身体。

   b 、如果类 B 有必要使用 A 的功能,则要分两种情况考虑:

1 )若在逻辑上 B 是 A 的“一种”( a kind of ),则允许 B 继承 A 的功能。如男人( Man )是人( Human )的一种,男孩( Boy )是男人的一种。那么类 Man 可以从类 Human 派生,类 Boy 可以从类 Man 派生。

2 )若在逻辑上 A 是 B 的 “ 一部分 ” ( a part of ),则不允许 B 继承 A 的功能,而是要用 A 和其它东西组合出 B 。例如眼( Eye )、鼻( Nose )、口( Mouth )、耳( Ear )是头( Head )的一部分,所以类 Head 应该由类 Eye 、 Nose 、 Mouth 、 Ear 组合而成,不是派生而成。

一只公鸡使劲地追打一只刚下了蛋的母鸡,你知道为什么吗?因为母鸡下了鸭蛋。

 

三、 虚函数与多态

结合“抽象基类”和“多态”有如下突出优点:

1 )应用程序不必为每一个派生类编写功能调用,只需要对抽象基类进行处理即可。这一招叫“以不变应万变”,可以大大提高程序的可复用性(这是接口设计的复用,而不是代码实现的复用)。

2 )派生类的功能可以被基类指针引用,这叫向后兼容,可以提高程序的可扩充性和可维护性。以前写的程序可以被将来写的程序调用不足为奇,但是将来写的程序可以被以前写的程序调用那可了不起。

 

JavaScript 的语言特性参考

JavaScript 语言是基于对象的( Object-Based ),而不是面向对象的( Object-Oriented )。之所以说它是一门基于对象的语言,主要是因为它没有提供封装、继承、多态等有关面向对象语言的许多功能。而是把其它语言所创建的复杂对象统一起来,从而形成一个非常强大的对象系统。

虽然 JavaScript 语言是一门基于对象的,但它还是具有一些面向对象的基本特征。它可以根据需要创建自己的对象,从而进一步扩大 JavaScript 的应用范围。

JavaScript 中的对象是由属性 (properties) 和方法 (methods) 两个基本的元素的构成的。前者是对象在实施其所需要行为的过程中,实现信息的装载单位,从而与变量相关联;后者是指对象能够按照设计者的意图而被执行,从而与特定的函数相联。

 

JavaScript 的面向对象特性参考

虽然 JavaScript 是脚本语言 , 但它所支持的面向对象编程也是非常强大的 . 虽然它没有类和实例 , 但它有对象 , 原型和隐式的继承。

一、 封装 (Wrap)

JavaScript 的对象封装,主要依靠 function 来实现。以下是一个简单的示例:

//*********************************************

// 定义 Pet( 宠物 ) 对象

//*********************************************

function Pet() {

        // 名称

        this.name = null;

        // 颜色

        this.color = null;

        // 获取名称

        this.getName = function() {

                return this.name;

        };

        // 设置名称

        this.setName = function(newName) {

                this.name = newName;

        };

        // 获取颜色

        this.getColor = function() {

                return this.color;

        };

        // 设置颜色

        this.setColor = function(newColor) {

                this.color = newColor;

        };

        // 定义一个需要实现的方法

        this.getFood = null;

        // 获取宠物的描述信息

        this.toString = function() {

                return "The pet is " + this.name +",it's "+this.color+",and it likes "+this.getFood()+".";

        };

}

二、 继承 (inheritance)

JavaScript 的继承的实现主要依靠 prototype( 原型 ) 来实现,下面为 Pet 类编写一个子类。

 

//*********************************************

// 定义 Cat( 猫 ) 对象

//*********************************************

function Cat() {

        // 实现 Pet 中定义的 getFood 方法

        this.getFood = function() {

                return "fish";

        };

}

 

// 声明 Cat 的原型,即 Cat 的父类

Cat.prototype = new Pet;

 

多层次继承

//*********************************************

// 定义 PersianCat( 波斯猫 ) 对象

//*********************************************

function PersianCat() {

}

 

// 声明 PersianCat 的原型,即 PersianCat 的父类

PersianCat.prototype = new Cat;

 

三、 重载 (override) 与多态 (Polymorphism)

// 重载 Pet 的 toString 方法

PersianCat.prototype.toString = function() {

        return "It's just a persian cat.";

};

 

注意: Override 和 Overload 的区别, JavaScript 是不支持 Overload 的,原因是……你自己想想吧。

方法的重写 Overriding 和重载 Overloading 是 Java 多态性的不同表现。重写 Overriding 是父类与子类之间多态性的一种表现,重载 Overloading 是一个类中多态性的一种表现。如果在子类中定义某方法与其父类有相同的名称和参数,我们说该方法被重写 (Overriding) 。子类的对象使用这个方法时,将调用子类中的定义,对它而言,父类中的定义如同被“屏蔽”了。如果在一个类中定义了多个同名的方法,它们或有不同的参数个数或有不同的参数类型,则称为方法的重载 (Overloading) 。 Overloaded 的方法是可以改变返回值的类型。

 

JavaScript OOP 框架介绍

一、 ProtoType.js

由 MVC web 框架 Ruby on Rails 开发并使用 JavaScript 基础库。这套库设计精良并且具有很好的可重用性和跨浏览器特性,使用 prototype.js 可以大大简化客户端代码的开发工作。 prototype.js 引入了类的概念,用其编写的类可以定义一个 initialize 的初始化函数,在创建类实例的时候会首先调用这个初始化函数。正如其名字, prototype.js 的核心还是 prototype ,虽然提供了很多可复用的代码,但没有从根本上解决 JavaScript 的开发和维护问题。

二、 Modello

Modello 是一个允许并且鼓励你用 JavaScript 来编写类的框架。传统的 JavaScript 使用构造函数来自定义对象,用 prototype 来实现继承。在 Modello 中,你可以忘掉晦涩的 prototype ,因为 Modello 使用类来设计对象,用类来实现继承,就像其它面向对象语言一样,并且使用起来更加简单。不信吗?请继续往下看。

使用 Modello 编写的类所具备如下特性:

私有成员、公共成员和静态成员
类的继承,多继承
命名空间
类型鉴别
Modello 还具有以下特性:

更少的概念,更方便的使用方法
小巧,只有两百行左右的代码
设计期和运行期彻底分离,使用继承的时候不需要使用 prototype ,也不需要先创建父类的实例
兼容 prototype.js 的类,兼容 JavaScript 构造函数
跨浏览器,跨浏览器版本
开放源代码, BSD licenced ,允许免费使用在个人项目或者商业项目中
 

三、 Bindows

Bindows 是一个用来编写安全健壮的 Rich Internet Applications 的软件开发工具包( SDK )。 Bindows 平台为瘦 Web 客户端提供了丰富的功能。

1.         基于类的面向对象 API ;

2.         一个完整的窗口系统,带有一组广泛支持的窗体小部件,包括菜单、表单、表格、滑块、量表以及更多;

3.         开发零接触 SOA 客户端应用程序的最好的工具包;

4.         内置 XML , SOAP 和 XML-RPC 支持;

5.         从单用户到企业级的支持。

 

四、 Qomo OpenProject

Qomo OpenProject 将在原生的 JavaScript 的基础上,实现更多的 OOP 特性,使得 JavaScript 能够方便地描述更庞大的框架,以及开发更复杂的 Rich Web Client / Application.

Qomo OpenProject 对将从 Delphi 和 C# 中借用很多的 OOP 特性和语法特性。因此,如果你需要深入了解 QomoJS 中 OOP Core 的实现技术,那么你可能需要了解一些 Delphi 或 C# 的基础知识。

Qomo OpenProject 将会由两个部分构成:

1 、 QomoJS : 在 JavaScript 的基础上进行扩展,使其支持完整的 OOP 特性,部分支持     一些其它高级语言的语法特性。它本身又由两个部分构成:

1.         QomoJS OOP Core : OOP 特性的实现内核

2.         QomoJS Framework : 语言特性的框架层和基础类库

2 、 QomoUI : 一套界面组件库。

 

五、 Atlas

Atlas 的设计宗旨不是要成为普普通通的 AJAX 类库,而是成为一个跨越客户端和服务器端开发以及整合两者交互的一个整体应用框架 (end-to -end application framework) ,它允许开发人员,既可以用 XML 声明的方式,也可以用脚本编程的方式,很快地集成组件,并且使得脚本功能与 ASP.NET 应用的集成既整洁,又不让人觉得唐突。

 

Atlas 提供了一个客户端的框架和服务,主要包括

1 。浏览器兼容层,把浏览器之间的差异封装出来,以利于其他层次的功能的浏览器独立性,目前支持 IE , Safari 和 Firefox

2 。脚本内核,包括了一个 Javascript 的整套类体系,允许你使用标准 OOP 里的构造,譬如,命名空间,类,接口,继承,枚举,代理 (delegate) 等等。目的是要提供一个机制把数据,逻辑和行为封装成类,使得开发人员可以象和其他编程语言一样来做脚本开发

3 。基类库,受 .NET 框架启发,提供了 StringBuilder, Debug, Event, 和 IDisposable 等方便的基础类型,同时通过 WebRequest, WebResponse 类提供了一个基于 XMLHTTP 的客户端 networking 层,在上面可以通过 MethodRequest 与 aspx 和 asmx 等服务端服务进行交互。也提供了序列化,特别是 JSON 序列化器。该类库也提供了可以和服务器端相应服务集成的 Profile 和认证服务

4 。组件模型和 UI 框架,引进了可以自描述本身对象模型的组件的概念,这些模型可以参与一个顶层的 Application 类管理的生命周期机制,可以通过以声明或编程的方式建立,可以通过绑定以及事件的形式来传输数据和交互。 UI 框架提供了与 DHTML UI 元素相关的控件,以及如何给这些控件附加行为的机制,譬如象 Drag/Drop 以及对输入控件数据的验证等等。

5 。控件和组件,提供了象计时器 (Timer) 和计数器 (Counter) 这样的组件以及象 ListView 和地图控件等的控件

Atlas 也提供了相应的服务器端基础设施,

1 。服务器控件框架,定义了一个新的控件 ScriptManager 来管理传回到客户端的脚本以及由服务器控件生成的 XML- 脚本标识。服务器控件也可以通过实现 IScriptComponent 来参与请求处理,同时,还提供了与客户端组件模型类型相对应的服务器端对象

2 。网络服务桥,允许客户端脚本访问普通的网络服务 (asmx) 以及 Indigo 风格的服务 (svc) ,也可以直接访问网页内声明的 WebMethod ,这是通过象下面这样的类似声明

 

<script src="MyService.asmx/js" />

 

由服务自动产生 javacript 代理类来实现的,同时提供了实现 JSON 协议调用服务器端服务的基础设施

 

3 。应用服务桥,通过网络服务桥提供了 ASP.NET 的几个应用服务,譬如可以通过成员服务做用户认证,以及通过 Profile 服务访问 / 更新用户数据等


详见 Nikhil Kothari blog 以及下面两个 ppt

Atlas Architecture Overview

PRS312 ASP.NET: Future Directions for Developing Rich Web Applications with Atlas (Part 1)

PRS420 ASP.NET: Future Directions for Developing Rich Web Applications with Atlas (Part 2)

 

参考资料:

1、  JavaScript 权威指南

2、  面向对象程序设计之体会

3、  JavaScript 面向对象编程, 第一部分: 继承

4、  javascript 的面向对象特性参考

5、  JavaScript OOP

6、  Prototype

7、  使用 prototype定义对象类型

8、  Modello

9、  使用 Modello编写JavaScript

10、              Bindows

11、              Qomo OpenProject

12、              Atlas

13、              Atlas的整体架构概述

14、              JSON

15、               

posted on 2006

posted on 2006-08-03 14:37  共同学习,共同进步  阅读(766)  评论(0编辑  收藏  举报