清单 2 中的代码出现了问题,尤其是它通过一个硬编码的 SQL 语句直接与一个硬编码的数据库进行通信。Yeeesh! 您能够想像开发人员测试这种 GUI 和相关数据库的挑战吗(顺便说一下,测试本应该简单得像测试一个 Web 页面一样)? 倘若对数据库的任何改动都将 影响到 GUI,那么要考虑修改系统的话会使情况变得更糟。
|
现在在脑海中考虑一下使用依赖性倒置原则设计的相同的系统。如图 2 所示,通过向应用程序添加两个组件来解除应用程序中的耦合是可能的:这两个组件分别是一个接口和一个实现:
图 2. 一个松散耦合的系统
在图 2 所示的应用程序中,GUI 依赖于一个抽象 —— 一个数据访问对象或 DAO。DAO 的执行直接依赖于数据库,但是 GUI 本身并没有陷入其中。以 DAO 的形式添加一个抽象可以从 GUI 实现将数据库实现解耦。一个接口会替代数据库与 GUI 代码相耦合。清单 3 显示了该接口。
public interface WidgetDAO { public String getOrderStatus(String widget); //.... } |
GUI 的
ActionListener
代码引用接口类型 WidgetDAO
(定义在清单 3 中)而不是接口的实际实现。在清单 4 中,GUI 的 getOrderStatus()
方法在本质上指定的是 WidgetDAO
接口:
private String getOrderStatus(String value) {
return dao.getOrderStatus(value);
}
对 GUI 完全隐藏了这个接口的实际实现,因为它是通过一个工厂来请求实现类型的,如清单 5 所示:
private WidgetDAO dao; //... private void initializeDAO() { this.dao = WidgetDAOFactory.manufacture(); } |
注意,清单 5 中的 GUI 中的代码只引用接口类型 —— GUI 中的任何地方都没有使用(或导入)接口的实现。这种对实现细节的抽象是灵活性的关键:它使您能够更换实现类型,而完全不会影响到 GUI。
还要注意,清单 5 中的 WidgetDAOFactory
是如何使 GUI 避开 WidgetDAO
类型的创建细节的。这些是工厂的任务,如清单 6 所示:
文章来源于领测软件测试网 https://www.ltesting.net/