面向接口的编程

Written by omencathay

现在越来越体会到面向接口的编程是面向对象编程的精粹,为什么呢?我们可以一下看看:

一、面向对象的理论体系

面向对象是一种世界观和方法论。从对象的角度对我们目之所及的事物观察、分析和提炼,这是一个层次的过程,也是一个从一般到抽象,再从抽象到一般的过程。这也是我们的程序开发实践所经历的一个过程。

对象就是我们要研究的客观世界的一些客体,包括实体的和逻辑层面的,实体是真真实实存在的,比如一个具体的人,一个具体的苹果;人有男人女人,苹果有各种苹果;但是他们都有共同的特征;所以男人女人可以统称为抽象的人,各种苹果可以统称为抽象的苹果,这个过程就是从一般到抽象的提炼,正是面向对象所说的继承,实体的东西可以从另外的实体或抽象的东西继承;而逻辑的层面往往是对象和对象之间的关系,比如人吃苹果,这样两个对象就发生了相互联系。而现实世界的对象内部往往是复杂的,由多个对象组成,这就是所谓的面向对象的包含关系,特殊一点的,有些对象组合成一个对象需要一定条件的存在,这就构成了对象的扩展关系。包含也有两种,根据组成对象的生命周期和依赖程度,又可分为组合和聚合,前者当对象消亡的时候,组成对象的各个部分也随之消亡,比如一个人死亡了,那么他的胳膊腿啥的也就没啥用了;后者当对象消亡的时候,组成对象的各个部分继续存在,比如汽车轮子在汽车拆解的时候还可以装到 别的汽车上去。

面向对象的编程,大量的采用了继承结构,总结出个体对象一般特性,就抽象成类,所以说类是这一群对象的统称,但是每个对象都有其特殊的地方,自己的行为方式和属性,通过继承结构就把这些对象的联系展现出来了,这是一种自下而上,而又自上而下的一种树形结构。

但是继承并不能解决所有问题,还有那些特质不一样的对象,如果发生关系会怎样呢?如对象间的互相调用,通信,协作---我们将之成为关联。我们不能硬生生的把它扯入继承和使用泛化,比如一个稍微复杂点的对象是由两个不同类的对象组成,这时候就更多的需要使用包含。

现实的世界是多样性和复杂的,我们需要一种清楚和简洁的方式来描述它,定义它,规范它,使之能够便利的为我们的系统所用,而不是简单的在一个继承结构中增加或者减少一个对象,或者任意的组合对象。

接口是在对象抽象成为类更高一个层面上的,就像一个构建中心和指挥中心,使得软件复用的思想可以发挥得淋漓尽致。

二、接口的定义性和标准性

接口是极端抽象的,它规约的是一个定义,一个标准,一个行为规范;任何系统的行为都必须按照我所规约的方式进行,你必须实现接口所定义的内容来实现,你必按照接口的标准来执行。在系统构建的初期,一个准确的定义是十分重要的,但是很多时候,这种定义也许并不完全,但是后期你可以将定义灵活的补充进去(增量),除非你原来的定义误解了客户的需要而使系统不得不重新架构。在程序实现上,例如java(就不说C++了,因为C++处处都有面向对象思想的例外),接口定义的东西,如果使用这个接口,那么实现它的类就必须完成它所定义的内容,不容有所违反,这样就不会在后期开发过程中对初期的要求有所遗忘和遗漏,你所需要做的工作就是实现,在一定约束下的实现,在这个基础上,当然你可以合理的进行扩展。

面向接口的编程层次结构,最顶层上应该是一系列的接口,定义系统的各种属性和行为,定义领域模型所抽象出来的实体和其中的逻辑关系;其次是一些定义对象间逻辑关系的抽象类和具体的类的实现。

三、分析的层面

面向对象编程,获取需求的主要工具是use case,而整个开发过程,恰恰是被use case驱动的,use case本身也只是对需求的一种语义性描述性的工具,分析是为设计做准备的,这个阶段应该是对系统的整个要求和要实现的功能有个整体的指向,这个阶段应当在语义上对备选需求,领域模型,功能需求,非功能需求有清晰的描述和定义。在设计阶段上将之映射为接口。当然我们并不是需要把所有的分析层面的定义都设计成接口,应当根据具体的系统行为来恰当使用。

四、设计的层面

为系统的实现,设计一个无缝的抽象,设计一个直接-精化的添加内容,而不改变结构,从分析类得来的设计类进一步细化成多个接口,成为更易于管理的部分。接口可以成为设计类和设计子系统的关键关联,它本身对于体系结构也是意义重大。面向对象的过程本身是以体系结构为中心的,在设计层面上,应当定义完整的、清晰的接口。通过特定的分类学手段将其划分到不同的设计包中去。

五、参看一个设计模式

系统的设计是需要高内聚低耦合的,这有利于软件复用,比如《Think in patterns》对象解耦的代理器模式, 其中基本的思想是简单的,从一个基类,用一个代理沿着这个提供了实现的类中将实现隐藏,使用者是看不到真正实现的:

//: proxy:ProxyDemo.java

// Simple demonstration of the Proxy pattern.

package proxy;

import junit.framework.*;

interface ProxyBase {

void f();

void g();

void h();

}

class Proxy implements ProxyBase {

private ProxyBase implementation;

public Proxy() {

implementation = new Implementation();

}

// Pass method calls to the implementation:

public void f() {

implementation.f();

}

public void g() {

implementation.g();

}

public void h() {

implementation.h();

}

}

class Implementation implements ProxyBase {

public void f() {

System.out.println("Implementation.f()");

}

public void g() {

System.out.println("Implementation.g()");

}

public void h() {

System.out.println("Implementation.h()");

}

}

public class ProxyDemo extends TestCase {

Proxy p = new Proxy();

public void test() {

// This just makes sure it will complete

// without throwing an exception.

p.f();

p.g();

p.h();

}

public static void main(String args[]) {

junit.textui.TestRunner.run(ProxyDemo.class);

}

} // /:~

当然,实现类没有必要实现与Proxy同样的接口。当Proxy有时为这个类说话时,就是它所调用的方法到基本的意图满足。然而,有一个公共的接口是便利的,实现被强迫去满足Proxy需要调用的所有方法。


来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/25966/viewspace-53321/,如需转载,请注明出处,否则将追究法律责任。

转载于:http://blog.itpub.net/25966/viewspace-53321/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值