在Java API设计中,面向接口编程的思想,以及接口和工厂的关系
现在的java API的设计中,提倡面向接口的编程,即在API的设计中,参数的传递和返回建议使用接口,而不是具体的实现类,如一个方法的输入参数类型应该使用Map接口,而不是HashMap或Hashtable等具体的实现类。这样做的好处是,程序容易扩展。如果使用Map作为参数,用户可以使用任何实现Map接口的类作为参数,而不是仅仅限制使用HashMap或Hashtable作为参数,使程序的实现更加灵活。
接口(Java的Interface),只定义了一些抽象的方法(也可以定义一些常量,但不鼓励这么做),没有具体的实现,这些抽象方法的具体实现,必须由实现(implements)接口的具体类来实现。接口反映了系统设计人员对系统的抽象理解。实际上,接口只是定义了一个规范和约束,要求实现类必须遵循这些规范和约束,大家编程时都要按照这个规范进行编程。
使用接口进行编程时,API的使用者只使用接口进行调用,而不管接口是如何实现的,这样你就可以随意更换接口的实现厂商(provider)。假如,你觉得厂商的接口实现不好,可以换一个厂商的实现类,甚至自己来实现,但确基本上不需要更改已经写好的应用程序(因为应用程序只对接口进行调用,而所有的实现类的接口都是相同的)。
如java.sql包定义了很多jdbc的接口,大家在进行jdbc编程时都只需要使用Connection、PreparedStatment、ResultSet等接口,而不需要考虑这些接口的具体实现类是什么。每种数据库,如Oracle、SQLServer、DB2的JDBC驱动则是由各个厂商提供具体实现类,来实现统一的JDBC API接口规范。
面向接口的编程中,工厂(Factory)的使用恐怕是最常用的,接口和工厂的关系是密不可分的,工厂,简单的说,就是生产接口实现类实例的类。可以说,在面向接口的编程中,工厂方法发挥了极其重要的作用。
在开发应用时,如何对接口进行调用,如何实例化接口对象?你无法通过类似于new Inteface1()等来进行实例化,因为接口是不能实例化的(接口即Java的Interface不是类,所有方法都是抽象的,所以不能实例化,能够实例化的只能是接口的实现类)。实例化接口类对象主要有两种方法:
1) 直接new 接口的实现类的实例,类似于
Map map=new HashMap(); //HashMap实现了Map接口
Interface1 instance=new ConcreteClass1(); //ConcreteClass1实现了Inteface1接口
在一个API内部,这样写无可厚非,因为对调用者是屏蔽的,你今后将HashMap改为hashtable,不会影响到API调用者的程序。但是对于一个API调用的程序来说,这样就不太好了。如下面的调用(出租车公司增加一种高级轿车):
Car car=new BenzCar(); //BenzCar实现了Car接口
carRentCompany.addSuperCar(car);
虽然可以这样,但这与面向接口的编程的原则不符,因为这要求你必须要知道接口的实现类,如果你有天想换一个实现类(如将奔驰车换成宝马车),就麻烦了,你必须找到你以前的应用程序源代码,将每一个调用接口实现类的地方都改过来,工作量比较大了。
还有一种更好的方法,就是使用工厂。
2) 使用工厂,如
Car car=CarFactory.getSuperCar();
carRentCompany.addSuperCar(car);
由工厂来提供实例化方法,你不必关心实例化类是哪一个。当然你必须知道工厂类是哪一个,更换接口实现的时候,你只需要修改工厂的方法就可以了,其余的都不需要更改了。如上面的场景,将奔驰车换成宝马车,只要更改CarFactory.getSuperCar()方法就可以了,用户调用API的程序不需要修改。
举个jdbc调用的例子:
Oracle的jdbc调用:
... ...
Class.forName("oracle.jdbc.driver.OracleDriver";);
Connection conn=DriverManager.getConnection(jdbcurl,username,password);
SQLServer的jdbc调用:
... ...
Class.forName("com.microsoft.jdbc.sqlserver.SQLServerDriver");
Connection conn=DriverManager.getConnection(jdbcurl,username,password);
MySQL的jdbc调用:
... ...
Class.forName("com.mysql.jdbc.Driver");
Connection conn=DriverManager.getConnection(jdbcurl,username,password);
这里,DriverManager就是工厂,通过getConnection()方法来生产出数据库连接对象Connection, 用户使用Connect就可以实现JDBC编程了。
但是,DriverManager是怎么知道使用的哪个数据库,使用哪个提供商的JDBC驱动来生产Connectin的吗?答案在这里,原因就在Class.forName()的过程中,Class.forName()是将一个类初始化,这里,调用不同厂商提供jdbc驱动时,使用了不同的jdbc驱动类的类名,该方法会初始化化该Driver类,该类在初始化时(static{}方法中)会初始化一个自己的Driver类实例,并将实例注册到DriverManager中(的一个Vector中),再通过DriverManager中的getConnection()方法找到Driver实例(通过jdbcurl),再调用Driver实例的getConnection()方法。Driver实例也是一个生产Connection接口实例的工厂。DriverManager实际上是一个保存了各个jdbc驱动的一个缓存管理类,缓存了各个驱动程序,并调用各个jdbc的驱动程序生产Connection对象。
可以看出,只需要更改Driver的类名,提供不同的jdbcUrl和用户、密码,就可以生产出一个数据库连接(Connection接口类的实例)。
建议:如果你使用配置文件来提供工厂类的名字,程序通过调用配置文件来读取工厂的类名,更换接口实现就更简单了,你只需要改配置文件就可以了,而不需要更改程序。
接口和工厂之间关系形象比喻:
接口就好比是产品规格,如螺母和螺钉的产品规格,规定了不同的大小尺寸,左旋等,工厂好比生产这些螺母和螺钉的加工企业,而接口的实例好比不同工厂生成出的螺母、螺钉的产品。每一个不同的工厂虽然生成出的不同螺母和螺钉产品,但都必须遵守这个产品规格,这样不同工厂生产出来的不同的螺母和螺钉才可以拧在一起使用,你也可以随意更换不同工厂生产出来的螺母或螺钉,而不会出现问题。
http://blog.sina.com.cn/s/blog_6f505d710100mxsy.html
在Java API设计中,面向接口编程的思想,以及接口和工厂的关系的更多相关文章
- (转)Java API设计清单
转自: 伯乐在线 Java API设计清单 英文原文 TheAmiableAPI 在设计Java API的时候总是有很多不同的规范和考量.与任何复杂的事物一样,这项工作往往就是在考验我们思考的缜密程度 ...
- API设计中性能提升的10种解决方法
api的设计涉及到的方面很多, 分类是一个基本的思考方式.如果可以形成一个系列性的文字,那就从性能开始吧. 就像任何性能一样,API 性能主要取决于如何响应不同类型的请求.例如:典型的电商场景,显示用 ...
- Java API设计CheckList
API设计原则:正确.好名.易用.易学.够快.够小.但我们从来不缺原则,〜〜〜 Interface 1.The Importance of Being Use Case Oriented,一个接口应当 ...
- Java API设计原则清单
在设计Java API的时候总是有很多不同的规范和考量.与任何复杂的事物一样,这项工作往往就是在考验我们思考的缜密程度.就像飞行员起飞前的检查清单,这张清单将帮助软件设计者在设计Java API的过程 ...
- 编写Java程序,使用面向接口编程模拟不同动物的吼叫声
返回本章节 返回作业目录 需求说明: 使用面向接口编程模拟不同动物的吼叫声 实现思路: 使用面向接口编程模拟不同动物吼叫声的实现思路: 定义发声接口Voice,在其中定义抽象吼叫方法sing(). 分 ...
- API设计中防重放攻击
HTTPS数据加密是否可以防止重放攻击? 否,加密可以有效防止明文数据被监听,但是却防止不了重放攻击. 防重放机制 我们在设计接口的时候,最怕一个接口被用户截取用于重放攻击.重放攻击是什么呢?就是把你 ...
- JAVA GUI设计中遇到的一个小问题
最近新学,大牛勿喷.. 写下笔记主要是记录自己常犯的错误,也方便新人解决问题学习参考. 问题:win7下设计GUI,文本框和密码框显示不出来. 我的解决方案: 1. JTextField text = ...
- restful api设计中的幂等性的理解。
以前就听说过这个词,但是最近看了一些文章,产生了一些疑惑, GET是幂等性.例如查一条数据,如果你给定一个id.那么你查多少次.都是这条数据,但是我疑问,这里的幂等性指的是,每次都返回一条.这个数量, ...
- API设计中响应数据格式用json的优点
通常我们再设计api返回时,都使用json格式返回,相比xml,他又有什么优点呢? 更直观易懂 占用空间更小 能与JavaScript跟好的兼容.js通过eval()进行Json读取. 支持多种语言. ...
随机推荐
- 极客无极限 一行HTML5代码引发的创意大爆炸
摘要:一行HTML5代码能做什么?国外开发者Jose Jesus Perez Aguinaga写了一行HTML5代码的文本编辑器.这件事在分享到Code Wall.Hacker News之后,引起了众 ...
- codeforces895E. Eyes Closed
题目链接 codeforces895E. Eyes Closed 题解 线段树维护期望和 写出修改两区间的相互影响 就是一个区间修改 emmm考试的代码过不去,这么松的spj都过不去Orz,每次和答案 ...
- 洛谷.2325.[SCOI2005]王室联邦(贪心)
题目链接 比较水的题 然而.. 首先可以考虑DFS 每B个分一个块,但是这样链底不会和上边相连 于是考虑从底下开始分,即在DFS完一个点时才将其加入栈中:当子树size==B时出栈 最后在根节点可能会 ...
- 51Nod.1237.最大公约数之和 V3(莫比乌斯反演 杜教筛 欧拉函数)
题目链接 \(Description\) \(n\leq 10^{10}\),求 \[\sum_{i=1}^n\sum_{j=1}^ngcd(i,j)\ mod\ (1e9+7)\] \(Soluti ...
- apache hive 1.0.0发布
直接从0.14升级到1.0.0,主要变化有: 去掉hiveserver 1 定义公共的API,比如HiveMetaStoreClient 当然,也需要使用新的beeline cli客户端. 不过最值得 ...
- 绘图 Painter转接口封装的方式
记录下思想 适用于业务逻辑相对单纯的一些画法,比如画背景(颜色,背景,边框等) 一个Draw方法中如果绘制比较复杂的话,就会导致代码混乱,而不灵活,每次需求更改就得重新画过,可重用性差. 以接 ...
- .NET:Threading and Exceptions
Do handle exceptions in threads. Unhandled exceptions in threads, even background threads, generally ...
- raw_socket(原始套接字)以及普通socket使用终极总结
一.传输层socket(四层socket,普通socket) 可参考本人以下博客: Windows Socket编程之UDP实现大文件的传输:http://blog.csdn.net/luchen ...
- iOS开发-获取属性和方法
iOS开发数据存储有两种方式,属性列表和对象编码,属性列表可以通过NSArray,NSMutableArray,NSMutableDictionary,存储对象我们可以通过归档和解档来完成.如果我们想 ...
- iOS开发-NSUndoManager撤销(undo)和重做(redo)
程序开发中我们经常会用到的两个快捷键Ctrl+Z和Ctrl+C,撤销和复制,Cocoa开发也可以实现这两个操作,为我们提供非常简单的操作类NSUndoManger,也可以称之为撤销管理器,NSUndo ...