`

业务层代码复用的一点建议

阅读更多
    传统的编写业务层的service类是为每个实体对象生成一个DAO,然后再每个实体DAO对应的service类中注入DAO属性作为服务层组件。这样做代码的可读性很好,层次分明,逻辑清晰。是一种较好的设计方式。

    如果考虑到代码软件最本质的特征-复用。减少不必要的编写。我们可以充分考虑Java语言的特征,诸如反射、多态、继承,以达到最大程度的重构。

    由此,我们在编写DAO层代码时,可设计一个BaseDAO类,抽象出最顶层的公有行为。
   
public void save(Object entityObj);
    public void update(Object entityObj);
    public Object findById(Class cls, Integer id);
    public List<Object> findByProperty(String hql, Object property);
    public List<Object> findByHql(String hql, Object[] values);
    public List<Object> findBySql(String sql, Object property);
    public List<Object> findBySql(String sql, Object[] values);


    在业务层,编写服务组件时,也可以抽象出一个BaseService类,集合公有行为。
   
public class BaseService {
          private BaseDAO baseDAO;

          // setter method
          // 共有方法
    }


    其他业务层服务组件,可以
extends BaseService
达到公有复用。

    当然,配置文件需配置bean的父子关系.

   
<bean id="" class="" parent="BaseService"></bean>


    这当然只是一种很简单的方法,你也可以从中抽象和重构出更简单更短小的设计。
分享到:
评论
49 楼 zk7019311 2011-05-26  
了解了解。。。。。
48 楼 lijie1819 2011-05-18  
看到LZ的设计思想,感觉和抽象工厂模式有点相像。
47 楼 liliugen 2011-04-07  
这个帖子还行
46 楼 今日不上网 2011-03-04  
skzr.org 写道
我自己就是这样做的,本着dao只做存储的思想
一个service对应N个dao
public interface IBaseDao {
	void saveOrUpdate(Object entity);
	
	@SuppressWarnings("unchecked")
	void saveOrUpdateAll(Collection entities);
	
	void delete(Object entity);
	
	<T> List<T> loadAll(Class<T> entityClass);
	
	<T> T get(Class<T> entityClass, Serializable id);
}

实现:
public class BaseDaoHibernateImpl extends HibernateDaoSupport implements IBaseDao {
	@Autowired
	public final void setupSessionFactory(SessionFactory sessionFactory) {
		setSessionFactory(sessionFactory);
	}

	@Override
	public void saveOrUpdate(Object entity) {
		getHibernateTemplate().saveOrUpdate(entity);
	}
	
	@Override
	@SuppressWarnings("unchecked")
	public void saveOrUpdateAll(Collection entities) {
		getHibernateTemplate().saveOrUpdateAll(entities);
	}
	
	@Override
	public void delete(Object entity) {
		getHibernateTemplate().delete(entity);
	}
	
	@Override
	public <T> List<T> loadAll(Class<T> entityClass) {
		return getHibernateTemplate().loadAll(entityClass);
	}
	
	@Override
	public <T> T get(Class<T> entityClass, Serializable id) {
		return getHibernateTemplate().get(entityClass, id);
	}
	
}


这样貌似查询功能很简单吧。
45 楼 cczakai 2011-03-03  
往往设计的时候容易过于追求细节,这样往往是过度设计。

我觉得目前设计模式解决复用性代码的主要模式应该是模板模式。

模板模式要做的是抽离不变部分集成到父类,变化部分由子类完成。

而很多情况,如果因为后续的变化而导致模板不可控的话,从本身来说,不是模板

出了问题,而是缺少对后续变化进行正确评估。

打比方,我们开发版本,一般有基线版本,但基线版本不能解决所有问题,因为每

个地区需求不一样,这样情况提供需要扩展机制,怎么扩展呢?

当我们把不变的解决了,现在就对变进行扩展,怎么去解决这才是核心问题。


如果因为变化,而不断去修改好的代码,导致结果破坏起初的设计意图,变得不可

控制,情况会更糟糕。

对扩展的接口,还要考虑对框架兼容性。扩展的功能,其实也相当添加新的功能,

而这种采用的主要是装饰模式。兼容性没办法解决时候,适当加个适配器。

当把扩展的接口定下来,我们怎么以00思想来处理基线与扩展的关系,扩展必须依

赖基线,就比如hibernate底层还不是用到基线了。这时候,我们需要对基线提供

管理类,扩展通过管理类来访问基线。


  管理接口  <>--------------基线接口(模板)----基线实现
    |                          |
   |                          |
   |      扩展接口-------Adapter模式------------》框架
   |              |            |
   |             |               |                
   --------具体扩展实现—————




由于环境,不能上次图片



44 楼 helloworldwyn 2010-12-10  
个人不太认同service的侵入设计
43 楼 devroller2 2010-11-15  
再说说这一点在我们项目中的实践吧,以便大家讨论。我们项目也是按照传统的做法,一个service接口+一个service实现类,结果导致接口的方法不断增加。代码相当难维护。后来我们把一些业务逻辑抽象出来并应用模板方法模式。具体是:
1、关键的service接口只是一个方法,有不同的实现类。
2、有一个默认抽象的实现类,实现模板方法。并有dao的一个属性。
3、dao接口也是只有结果方法。

业务是这样的,我们有不同的业务类型,不同的业务类型有些逻辑不一样,但相同的逻辑是要授权、校验等,并把处理结果保存到数据库。

不同业务类型,从web来的数据被service处理后,保存到db时,对应的表有不一样了,怎么办?我们可以通过注入不同的dao对象就可以实现了。

这个例子是说明当dao实现类不一样的时候service代码如何被复用。


42 楼 devroller2 2010-11-15  
devroller2 写道
关于这个话题我也来说说:
1、相对来说service层应该是比较粗的粒度,比如方法都是很多逻辑在里面,以便事务控制。
2、service层很多人理解错(个人认为)。为啥?某service实现类只有一个,我们要知道,接口的存在是认为它有不同的实现的,可是多数只有一个!并且不断的往里加方法,多了就很难看了。如果不是很简单的应用最好对业务领域建模,并通过service让其对外提供服务。
3、Dao层不要尽量跟业务逻辑相关,dao层的接口一般不同的实现是指jdbc、hibernate、ibatis等。当然不是不可以,我们项目中就跟考虑了业务逻辑。用起来很爽(当然是指扩展、维护性),

我觉得《spring 专业开发指南》这边书写的不错,不仅仅讲spring技术,对这个话题也有所描述。很厚的一本书

41 楼 devroller2 2010-11-15  
关于这个话题我也来说说:
1、相对来说service层应该是比较粗的粒度,比如方法都是很多逻辑在里面,以便事务控制。
2、service层很多人理解错(个人认为)。为啥?某service实现类只有一个,我们要知道,接口的存在是认为它有不同的实现的,可是多数只有一个!并且不断的往里加方法,多了就很难看了。如果不是很简单的应用最好对业务领域建模,并通过service让其对外提供服务。
3、Dao层要尽量跟业务逻辑相关,dao层的接口一般不同的实现是指jdbc、hibernate、ibatis等。

我觉得《spring 专业开发指南》这边书写的不错,不仅仅讲spring技术,对这个话题也有所描述。很厚的一本书
40 楼 cgttian 2010-09-24  
pjcai 写道
感觉楼主理解的service没有真正做到service的职责。dao不应该与service存在一一对应的关系,否则你的service仅仅是dao的一层壳,没有太多存在的必要。service与dao应该是1对n的关系(n>=1)

基本同意...
39 楼 smallsnake 2010-09-20  
<div class="quote_title">frankhanmei 写道</div><div class="quote_div"><div class="quote_title">pjcai 写道</div>
<div class="quote_div">感觉楼主理解的service没有真正做到service的职责。dao不应该与service存在一一对应的关系,否则你的service仅仅是dao的一层壳,没有太多存在的必要。service与dao应该是1对n的关系(n&gt;=1)</div>
<p> </p>
<p>同意 PJCAI 的观点,DAO是对数据库(底层)操作的实现(1vs1),Service 是对DAO的修饰,一个Service方法可以有多个DAO方法组成(事务,同步,异步)。</p>
<p> </p></div><br/>同上,DAO层就应该功能单一,以便重用
38 楼 frankhanmei 2010-09-20  
<div class="quote_title">pjcai 写道</div>
<div class="quote_div">感觉楼主理解的service没有真正做到service的职责。dao不应该与service存在一一对应的关系,否则你的service仅仅是dao的一层壳,没有太多存在的必要。service与dao应该是1对n的关系(n&gt;=1)</div>
<p> </p>
<p>同意 PJCAI 的观点,DAO是对数据库(底层)操作的实现(1vs1),Service 是对DAO的修饰,一个Service方法可以有多个DAO方法组成(事务,同步,异步)。</p>
<p> </p>
37 楼 ldbjakyo 2010-09-19  
泛型用在dao 层 解决不少 乱套的问题
36 楼 gtssgtss 2010-09-18  
我在thinking in java里看到说,继承只应该在一种情况下被使用,那就是子类需要向上转型,其他情况下,不应该使用继承
35 楼 bbym010 2010-09-18  
一般是一对N吧
34 楼 liwenjie 2010-09-10  
这个也是精华帖??过了吧
33 楼 wmiao89620 2010-09-06  
很实在呀 呵呵~
32 楼 xiaoyuqi00 2010-08-29  
javaeye 有价值的帖子越来越少了
31 楼 sam_chi 2010-08-24  
恩,加强对泛型的支持会更好,如:
public <E extends Object> E findById(Class<E> cls, Integer id);
30 楼 qyhdt 2010-08-20  
楼主加油哦 你就快成功了 哈哈

相关推荐

    CreateCodeC#三层结构代码生成软件V1..0.1

    总的来说,"CreateCodeC#三层结构代码生成软件V1.0.1"是一个旨在帮助C#开发者快速构建三层架构应用的工具,利用反射和泛型技术自动创建代码,但其当前版本可能存在一些问题,推荐使用更新的版本。理解和掌握这些知识...

    ASP.net2.0三层架构(PDF版本)

    8. **测试和调试**:提供一些关于如何测试和调试三层架构应用的建议。 《文档声明.txt》可能包含关于该PDF文档的版权信息、作者声明或使用条款,但具体内容需要打开文件查看。 总的来说,ASP.NET 2.0三层架构是一...

    jeesite开源代码,,提高开发效率,,非常建议下载下来研究,官网上也有。

    2. **Spring MVC**:作为Spring框架的一部分,Spring MVC负责处理HTTP请求,提供模型-视图-控制器(MVC)的架构模式,使得业务逻辑、数据和视图层分离,提高了代码的可维护性和可测试性。 3. **MyBatis**:JeeSite...

    关于VB的相关资料,有一些相关系统的代码

    此外,VB也支持模块化编程,可以创建标准模块或窗体模块来封装功能,提高代码复用性。比如,你可以创建一个通用的数据库连接模块,供多个系统调用,实现数据访问的统一。 VB的小系统通常包括以下几个部分:用户界面...

    C_代码规范

    - 通过继承和多态提高代码的复用性。 #### 四、调试技巧 调试是软件开发过程中不可或缺的一部分,正确的调试方法可以大大提升开发效率。文档中提到的一些调试技巧包括: ##### 4.1 编译时的错误 在编译阶段发现...

    如何编写无法维护的代码

    1. **妙用宝宝起名大全**:建议开发者使用一些看似随意的名字,如“Fred”或“adsf”。这类名字简单易记,但缺乏意义,使得其他开发者难以理解其用途。 2. **单字母变量名**:使用单字母变量名(如`a`、`b`、`c`等)...

    微信小程序代码-《重邮》代码.zip

    5. **utils** 文件夹:可能包含一些通用的工具函数,如网络请求、数据处理、日期格式化等,方便在多个页面之间复用。 6. **images** 或 **assets** 文件夹:存储图片资源,这些图片会被引用到小程序的各个页面中。 ...

    J2EE项目代码编写规范.zip

    以上只是一些基本的J2EE代码编写规范要点,实际的规范文档会包含更多细节,比如编码风格、日志记录、国际化与本地化处理、多线程编程的注意事项等。遵循这些规范,可以显著提高J2EE项目的质量和可维护性。

    C编码规范和注意事项

    其他层则包含一些辅助性的文档和文件。 5. 文件结构:在文件管理方面,文档规定了文件的结构,包括版权和版本声明、头文件的结构、定义文件的结构。这是为了确保项目文件的整洁和一致性。 6. 命名规则:包括对枚举...

    express 项目分层实践详解

    上次我们搭建了一个基本的 express 后台,但是这样的项目结构的可扩展性,维护性和代码复用性都不是很好,参照之前学习 JavaWeb 时候的四层架构设计,用分层的思想来对 express 进行一点小优化,进一步提高代码的可...

    SSH项目构架规范详解

    为了解决这些问题,一种改进的SSH架构被提出,通过重新定义分层结构,实现业务代码的共享和复用。主要变化在于: 1. **业务代码统一实现IBusinessService接口**,这使得Action类的数量得以减少,因为大多数业务逻辑...

    weather-project

    2. **weather-common**: 这个模块可能包含了项目中可复用的工具类、常量、枚举等通用组件,例如日期时间处理、字符串操作等,旨在提高代码的重用率和减少代码冗余。 3. **weather-manager-web**: 这部分是Web应用的...

    web开发注意事项(一).docx

    6. **简化SQL操作**:尽量避免复杂的多表联查,这会增加数据库压力,不利缓存,并降低代码复用性。尽量使用简单查询。 7. **批量获取数据**:在循环中避免频繁执行findXXById,可以使用findXXByIds批量获取数据,...

    基于javaweb的运动与健康管理系统源代码和数据库.zip

    Servlet负责处理服务器端的业务逻辑,JSP用于生成动态网页,而JavaBean则封装了可复用的业务组件。 2. **MVC设计模式**: Model-View-Controller模式是JavaWeb开发中常用的设计模式,用于分离应用程序的数据模型、...

Global site tag (gtag.js) - Google Analytics