`
wsjjasper
  • 浏览: 13587 次
  • 性别: Icon_minigender_1
文章分类
社区版块
存档分类
最新评论

2.基于Spring的应用程序的设计和实现(接口驱动设计)

阅读更多

接口驱动设计

 

 

接口驱动设计几乎已经成为了一种实现应用程序的习惯,无论是框架还是你使用的一些标准(Spring,jboss,guice,EJB等等)。这样设计的一个主要目标是进一步的简化应用程序开发。在详细讨论设计细节之前,有必要阐述下为什么这样设计如此重要,以及spring是如何简化它的。

 

为什么要接口驱动设计

 

设计成接口驱动而不是直接使用类有很多原因,但也许最重要的原因就是降低耦合。如果一个容器使用接口来编写,当它有问题时将很容易被替换。这项特性将使你能够方便的将一种实现转为另一种,而不需要影响其他的代码。事实上,这么做你甚至可以使你的程序可以使用多种不同的实现并存。比如,当你使用spring 的prifile特性时,你能够在不影响其他代码的情况下提供给一个接口以不同的实现。不仅如此,在java里,一个类只能继承一个父类却能够实现多个不同的接口。通过定义接口,你不用使用一个类去继承特定的类(非常大的抽象类),而是实现多个接口。另一个好处,如我们在第七章讨论的,当你使用面向切面思想时,使用接口驱动让你能够使用spring的introduction特性,从而在你的类中 “嵌入”特定的接口,同时又不影响其他代码和逻辑。


在测试方面,一个主要的好处是通过降低耦合使得测试更容易。作为开发者的一员,我们一直在寻求新的方式来改进我们的程序测试覆盖率。通过接口驱动设计,我们可以方便的使用模拟来替换那些接口实现,从而使我们的测试更灵活。比如,当我们做单元测试一个web controller的时候,我们只想关注是否这个controller工作正常,并且假定那些service都是没问题的。在这种情况下,使用模拟service将会非常的合适。

 

工厂模式

 

在实现程序时可能会碰到一个非常关键的问题:将所有的容器都定义为接口后,程序将如何确定它使用哪个实例?


一个传统的方法是使用工厂模式。工厂模式定义了那些用来实现接口的实现类。在这种情况下,容器是以接口定义而不是类定义的。假设有个业务接口叫OrderService。其他容器需要获得这个实例,但又不能确定何时要,该如何实现? 通常做法是创建一个工厂类如12-1代码。

 

 

//Listing 12-1. A Basic Factory Class Implementation
package com.apress.prospring3.ch12.factory;

import com.apress.prospring3.ch12.service.OrderService;
import com.apress.prospring3.ch12.service.impl.DefaultOrderServiceImpl;

public class BasicFactory {
	private static final BasicFactory instance;
	private OrderService orderService;
	static {
		instance = new BasicFactory();
	}

	public static BasicFactory getlnstance() {
		return instance;
	}

	public BasicFactory() {
		this.orderService = new DefaultOrderServiceImpl();
	}

	public OrderService getOrderService() {
		return this.orderService;
	}
}
 

 

这是个非常简单的工厂实现例子。现在程序要得到OrderService的实现只要使用BasicFactory的getOrderService()方法就可以了。

 

传统工厂模式的缺点

 

传统的工厂模式主要有如下三个缺点:


-除非重新编译,否则没法修改实现类


-容器没有办法简单的使用需要的实现类。容器必须对工厂类有所了解从而知道该调用工厂类的哪个方法来获得实现。


-无法简单的修改实现类。在12-1例子中,返回了一个的实例,但是假设我们想同时需要多个实例,我们不得不修改并重新编译工厂类,我们将在接下来的三个小节中对这些缺点的详细讨论

 

可外部配置的工厂类

 

在12-1的例子中,你可以看到修改实现类意味着修改并重新编译。接口驱动设计的一个好处就是可以方便的替换实现类。然而,重新编译工厂类使其大打折扣。在过去的许多工程中,那时还没有Spring, 我们通常创建一个可以在外部配置文件中配置的工厂类来避免这个问题。这的确解决了开头的问题,但是它也使得我们不得不承担更多的开发工作,更糟的是,即使如此还是有问题。。。

 

显示的多实现支持

 

显示的多实现支持也许是传统工厂模式最大的缺点。在类BasicFactory中,getOrderService()方法,只能返回唯一一个特定的实现,无法自由选择。于是很自然的我们想到了如12-2的实现方式:

 

 

//Listing 12-2. Basic Support for Multiple Implementations
package com.apress.prospring3.ch12.factory;

import com.apress.prospring3.ch12.service.OrderService;
import com.apress.prospring3.ch12.service.impl.DefaultOrderServiceImpl;
import com.apress.prospring3.ch12.service.impl.SuperOrderServiceImpl;

public class MultiFactory {
	private static final BasicFactory instance;
	private OrderService orderService;
	private OrderService superOrderService;
	static {
		instance = new BasicFactory();
	}

	public static BasicFactory getInstance() {
		return instance;
	}

	public MultiFactory() {
		this.orderService = new DefaultOrderServiceImpl();
		this.superOrderService = new SuperOrderServiceImpl();
	}

	public OrderService getOrderService() {
		return this.orderService;
	}

	public OrderService getSuperOrderService() {
		return this.superOrderService;
	}
}
 

 

在这种实现方式下,容器可以调用getSuperOrderService()方法来获得SuperOrderServiceImpl实例。然而,这种方式恰恰否定了工厂的好处。虽然容器没有与特定的实现类耦合,但是与工厂的方法耦合了。另一个缺点是每次添加新实现类的修改都得重新编译,这也很不方便。


另外一个解决方案是在调用getOrderService()方法时把类型传进去,根据传进去的类型来返回这个类型的实现类。这种方式也有很多问题,比如它只能通过类来工作,意味着两个相同类型的实例将无法实现。你将同时发现如果你有许多不同的实现类时,getOrderService()

方法将变得很大很难维护。


相对而言,一个比较好的办法是使用查找方式的方法来让容器选择需要的实现类。所以,不是调用getOrderService(),而是调用getOrderService("someKey")。但即使如此,问题还是存在,为了使得足够灵活,每个容器必须使用特定的key来获取实现,key将变得很多很难维护。而且当需要更新实现时,仍然得修改代码并编译。问题的症结在于容器必须自己去决定使用哪个实现类,所以无论如何,传统的工厂类都会遇到问题。

 

多个实例模型支持

 

另一个问题是我们的容器同时需要多个实现的实例。这个问题和刚才的一样,问题在于容器必须自己去决定使用哪个实现类。对返回类型都无法支持,对于返回的实例数量当然也是没有办法支持的。

 

基于Spring的接口驱动设计

 

    Spring的接口驱动设计对应用程序开发影响很大。因为它能统一管理所有的容器,你压根就不需要担心如何去设计工厂类来获得实现。


在表面看来,当你用spring构建一个接口驱动的程序时,最大的好处是你不用写大量冗余的代码。只需通过一些配置即可。其实,这都归功于spring的依赖注入机制。凭借它,spring去除了容器对于实现类的依赖,只要让容器运行spring注入即可。


依赖注入即是说spring能够提供一个实现类的实例给任何容器,同时不需要在容器中编写任何代码。这是因为spring可以自由的管理任何实现实例的完整生命周期。总之就是spring有我们需要的所有接口驱动设计所必须的特征,从而使我们从如何获得接口实现的问题中得以脱身。


下一节:基于Spring的应用程序的设计和实现(构建领域对象模型) http://wsjjasper.iteye.com/blog/1574590
 

分享到:
评论

相关推荐

    org.springframework.web.struts-3.1.0.M2.jar

    `org.springframework.web.struts-3.1.0.M2.jar`是Spring为Struts提供的一个适配器,它使得Spring框架能够无缝地集成到Struts应用程序中。该版本号3.1.0.M2表明这是该组件的里程碑2版本,通常在正式版本发布前,M...

    org.springframework.core.jar

    2. **资源管理**:`org.springframework.core.io`包定义了资源接口,统一了文件、URL、输入/输出流等各种资源的访问方式,增强了资源操作的灵活性和可扩展性。 3. **元数据与注解处理**:`org.springframework.core...

    精通Spring4.x+企业应用开发实战 配套光盘(源码+资源)

    通过光盘中的源码,读者可以学习到如何将这些概念应用于实际项目,包括如何配置Spring、如何设计和实现业务逻辑、如何处理数据库操作以及如何进行单元测试等。资源部分可能包含示例数据库脚本、配置文件模板和其他...

    spring框架所需要的lib包

    7. `spring-webmvc`: 是Spring的Web MVC框架,用于构建RESTful服务和Web应用程序。 8. `spring-jdbc`: 提供了对JDBC的抽象层,简化数据库访问。 9. `spring-tx`: 支持声明式事务管理,使得事务处理更加简单。 10. `...

    Spring中文帮助文档

    12.2.4. 不使用回调的基于Spring的DAO实现 12.2.5. 基于Hibernate3的原生API实现DAO 12.2.6. 编程式的事务划分 12.2.7. 声明式的事务划分 12.2.8. 事务管理策略 12.2.9. 容器资源 vs 本地资源 12.2.10. 在应用...

    Spring API

    12.2.4. 不使用回调的基于Spring的DAO实现 12.2.5. 基于Hibernate3的原生API实现DAO 12.2.6. 编程式的事务划分 12.2.7. 声明式的事务划分 12.2.8. 事务管理策略 12.2.9. 容器资源 vs 本地资源 12.2.10. 在应用...

    基于Spring Boot MySQL实现软件工程课程思政微平台,小程序应用【优质毕业设计、课程设计项目】.zip

    开发者可以通过阅读源码来学习Spring Boot的注解驱动编程、Spring Data JPA与MySQL的集成、以及如何设计和实现RESTful API接口。 总的来说,这个项目为学习者提供了一个实战性的平台,涵盖了Java Web开发中的诸多...

    Spring.3.x企业应用开发实战(完整版).part2

    13.6.4 Web应用程序中调度器的启动和关闭问题 13.7 小结 第14章 使用OXM进行对象XML映射 14.1 认识XML解析技术 14.1.1 什么是XML 14.1.2 XML的处理技术 14.2 XML处理利器:XStream 14.2.1 XStream概述 14.2.2 快速...

    基于微信小程序的微型咨讯系统的设计和实现.pdf

    SpringBoot是一个独立的、生产级别的基于Spring框架的应用框架,它的主要作用是简化Spring应用的初始搭建以及开发过程。SpringBoot提供了一系列大型项目的实践配置,让开发者能更快速地启动新项目,并且它能和Maven...

    基于Spring框架的云笔记设计与实现.docx

    总结,基于Spring框架的云笔记设计与实现是一个综合运用现代Web技术和软件工程方法的项目,它不仅涵盖了前端交互、后端服务、数据库设计等多个方面,还强调了数据安全和用户体验。通过这样的设计,我们可以构建一个...

    spring 3.x企业应用开发实战的jar包

    在Spring 3.x企业应用开发实战中,使用到的各种jar包是实现高效、灵活和可扩展的应用程序架构的关键。这些库提供了丰富的功能,包括依赖注入、面向切面编程、数据持久化、Web MVC以及与其他技术的集成。以下是这些...

    springboot520基于Spring Boot的民宿租赁系统的设计与实现pf.zip

    综上所述,基于Spring Boot的民宿租赁系统设计与实现涉及多个技术层面,包括前后端开发、数据库设计、API接口规范、安全机制以及性能优化。通过合理的架构设计和技术选型,我们可以构建出稳定、高效的民宿租赁平台,...

    项目配置文件( spring-mvc.xml spring-mybatis.xml web.xml log4j.properties)

    通过这个配置,Spring可以管理MyBatis的SqlSession,实现数据库操作的事务控制,并且能够自动扫描和加载Mapper接口,使得SQL查询可以通过注解或者XML文件进行定义。 3. **web.xml**: 这是Web应用的部署描述符,定义...

    基于Spring Boot和Spring Cloud实现微服务架构学习(一).pdf

    本文将深入探讨如何基于Spring Boot和Spring Cloud实现微服务架构。Spring Boot是Spring框架的一个重要组成部分,它的主要目标是简化Spring应用的初始搭建以及开发过程。通过内置的Tomcat服务器和自动配置特性,...

    org.springframework.web-2.5.6.A.jar

    Spring Web模块是Spring框架的核心部分,它提供了用于构建基于Java的Web应用程序的基础架构。这个`.jar`文件包含了处理HTTP请求、响应,以及与Servlet容器交互的关键类和接口。它使得开发者能够更轻松地实现MVC...

    基于Spring Boot MySQL实现助农旅游平台管理系统,Android应用【优质毕业设计、课程设计项目】.zip

    本项目是一个基于Spring Boot框架和MySQL数据库的助农旅游平台管理系统,同时也包含了Android应用程序的开发。这个项目适合作为优质的毕业设计或课程设计项目,能够帮助学生深入理解和实践Web开发和移动应用开发的...

    外卖点餐系统-基于spring+vue的外卖点餐系统设计与实现

    Spring Boot是Java开发中的热门框架,它简化了Spring应用程序的创建和运行过程。在本系统中,Spring Boot作为核心后端框架,提供了依赖管理和自动配置功能,使得开发者可以快速搭建服务器端应用。通过注解驱动的方式...

    基于Spring Boot MySQL实现手办定制销售系统【优质毕业设计、课程设计项目】.zip

    本项目是一个基于Spring Boot框架和MySQL数据库实现的手办定制销售系统,旨在提供一个全面的、易用的在线销售平台,适合用作毕业设计或课程设计的实践项目。这个系统不仅包含了程序源代码,还配备了完整的数据库设计...

    任务书springboot146基于Spring Boot的可盈保险合同管理系统的设计与实现任务书.doc

    1. **Spring Boot框架**:Spring Boot是一个基于Spring框架的快速开发工具,它简化了配置,集成了大量的常用库,使得开发者能够快速构建健壮的Web应用程序。在本项目中,Spring Boot将作为核心框架,用于构建可盈...

Global site tag (gtag.js) - Google Analytics