在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读取. 支持多种语言. ...
随机推荐
- IdentityServer4-客户端的授权模式原理分析(三)
在学习其他应用场景前,需要了解几个客户端的授权模式.首先了解下本节使用的几个名词 Resource Owner:资源拥有者,文中称“user”: Client为第三方客户端 ...
- 微信小程序:一起玩连线,一个算法来搞定
微信小程序:一起玩连线 游戏玩法 将相同颜色的结点连接在一起,连线之间不能交叉. 算法思想 转换为多个源点到达对应终点的路径问题,且路径之间不相交.按照dfs方式寻找两个结点路径,一条路径探索完之后, ...
- Spring框架学习09——基于AspectJ的AOP开发
1.基于注解开发AspectJ (1)AspectJ注解 基于注解开发AspectJ要比基于XML配置开发AspectJ便捷许多,所以在实际开发中推荐使用注解方式.关于注解的相关内容如下: @Aspe ...
- bzoj 2013 上升计数
题意: 给一个数集和一个数d,问满足下列要求的排列数(相同的数要区分): a[i]+d>=a[i+1] ( i in [1,n) ) 因为数的给出顺序不重要,所以先排序,假如我们已经解决了前i ...
- 利用dockerfile定制镜像
利用dockerfile定制镜像 镜像的定制就是定制每一层所添加的配置.文件.如果可以吧每一层修改.安装.构建.操作的命令都写入到一个脚本,用脚本来构建.定制镜像,这个脚本就是dockerfile. ...
- exce中42093和日期之间的关系
在EXECEL中数字0 代表日期 1900-1-0 ,即这个日期为起始日期,算是第0天数字1 代表日期 1900-1-1 ,即第一天数字2 代表日期 1900-1-2 ,即第二天......数字415 ...
- cocos2dx之保存截屏图片
http://blog.csdn.net/ganpengjin1/article/details/19088921 我们要保存当前的运行的scene的截图的话,我用到CCRenderTexture,看 ...
- ConcurrentHashMap 的实现原理
概述 我们在之前的博文中了解到关于 HashMap 和 Hashtable 这两种集合.其中 HashMap 是非线程安全的,当我们只有一个线程在使用 HashMap 的时候,自然不会有问题,但如果涉 ...
- 使用Let’s Encrypt生成免费的SSL证书
SSL(安全套接层,Secure Sockets Layer),及其继任者 TLS (传输层安全,Transport Layer Security)是为网络通信提供安全及数据完整性的一种安全协议.TL ...
- Windows平台下tomcat 性能调优
Tomcat 线程查看工具: https://blog.csdn.net/jrainbow/article/details/49026365 16G内存 Tomcat并发优化.内存配置.垃圾回收.宕机 ...