业务层代码复用的1点建议
业务层代码复用的一点建议
传统的编写业务层的service类是为每个实体对象生成一个DAO,然后再每个实体DAO对应的service类中注入DAO属性作为服务层组件。这样做代码的可读性很好,层次分明,逻辑清晰。是一种较好的设计方式。
如果考虑到代码软件最本质的特征-复用。减少不必要的编写。我们可以充分考虑Java语言的特征,诸如反射、多态、继承,以达到最大程度的重构。
由此,我们在编写DAO层代码时,可设计一个BaseDAO类,抽象出最顶层的公有行为。
在业务层,编写服务组件时,也可以抽象出一个BaseService类,集合公有行为。
其他业务层服务组件,可以
当然,配置文件需配置bean的父子关系.
这当然只是一种很简单的方法,你也可以从中抽象和重构出更简单更短小的设计。
基本同意...
这样貌似查询功能很简单吧。
传统的编写业务层的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>
这当然只是一种很简单的方法,你也可以从中抽象和重构出更简单更短小的设计。
30 楼
qyhdt
2010-08-20
楼主加油哦 你就快成功了 哈哈
31 楼
sam_chi
2010-08-24
恩,加强对泛型的支持会更好,如:
public <E extends Object> E findById(Class<E> cls, Integer id);
public <E extends Object> E findById(Class<E> cls, Integer id);
32 楼
xiaoyuqi00
2010-08-29
javaeye 有价值的帖子越来越少了
33 楼
wmiao89620
2010-09-06
很实在呀 呵呵~
34 楼
liwenjie
2010-09-10
这个也是精华帖??过了吧
35 楼
bbym010
2010-09-18
一般是一对N吧
36 楼
gtssgtss
2010-09-18
我在thinking in java里看到说,继承只应该在一种情况下被使用,那就是子类需要向上转型,其他情况下,不应该使用继承
37 楼
ldbjakyo
2010-09-19
泛型用在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>=1)</div>
<p> </p>
<p>同意 PJCAI 的观点,DAO是对数据库(底层)操作的实现(1vs1),Service 是对DAO的修饰,一个Service方法可以有多个DAO方法组成(事务,同步,异步)。</p>
<p> </p>
<div class="quote_div">感觉楼主理解的service没有真正做到service的职责。dao不应该与service存在一一对应的关系,否则你的service仅仅是dao的一层壳,没有太多存在的必要。service与dao应该是1对n的关系(n>=1)</div>
<p> </p>
<p>同意 PJCAI 的观点,DAO是对数据库(底层)操作的实现(1vs1),Service 是对DAO的修饰,一个Service方法可以有多个DAO方法组成(事务,同步,异步)。</p>
<p> </p>
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>=1)</div>
<p> </p>
<p>同意 PJCAI 的观点,DAO是对数据库(底层)操作的实现(1vs1),Service 是对DAO的修饰,一个Service方法可以有多个DAO方法组成(事务,同步,异步)。</p>
<p> </p></div><br/>同上,DAO层就应该功能单一,以便重用
<div class="quote_div">感觉楼主理解的service没有真正做到service的职责。dao不应该与service存在一一对应的关系,否则你的service仅仅是dao的一层壳,没有太多存在的必要。service与dao应该是1对n的关系(n>=1)</div>
<p> </p>
<p>同意 PJCAI 的观点,DAO是对数据库(底层)操作的实现(1vs1),Service 是对DAO的修饰,一个Service方法可以有多个DAO方法组成(事务,同步,异步)。</p>
<p> </p></div><br/>同上,DAO层就应该功能单一,以便重用
40 楼
cgttian
2010-09-24
pjcai 写道
感觉楼主理解的service没有真正做到service的职责。dao不应该与service存在一一对应的关系,否则你的service仅仅是dao的一层壳,没有太多存在的必要。service与dao应该是1对n的关系(n>=1)
基本同意...
41 楼
devroller2
2010-11-15
关于这个话题我也来说说:
1、相对来说service层应该是比较粗的粒度,比如方法都是很多逻辑在里面,以便事务控制。
2、service层很多人理解错(个人认为)。为啥?某service实现类只有一个,我们要知道,接口的存在是认为它有不同的实现的,可是多数只有一个!并且不断的往里加方法,多了就很难看了。如果不是很简单的应用最好对业务领域建模,并通过service让其对外提供服务。
3、Dao层要尽量跟业务逻辑相关,dao层的接口一般不同的实现是指jdbc、hibernate、ibatis等。
我觉得《spring 专业开发指南》这边书写的不错,不仅仅讲spring技术,对这个话题也有所描述。很厚的一本书
1、相对来说service层应该是比较粗的粒度,比如方法都是很多逻辑在里面,以便事务控制。
2、service层很多人理解错(个人认为)。为啥?某service实现类只有一个,我们要知道,接口的存在是认为它有不同的实现的,可是多数只有一个!并且不断的往里加方法,多了就很难看了。如果不是很简单的应用最好对业务领域建模,并通过service让其对外提供服务。
3、Dao层要尽量跟业务逻辑相关,dao层的接口一般不同的实现是指jdbc、hibernate、ibatis等。
我觉得《spring 专业开发指南》这边书写的不错,不仅仅讲spring技术,对这个话题也有所描述。很厚的一本书
42 楼
devroller2
2010-11-15
devroller2 写道
关于这个话题我也来说说:
1、相对来说service层应该是比较粗的粒度,比如方法都是很多逻辑在里面,以便事务控制。
2、service层很多人理解错(个人认为)。为啥?某service实现类只有一个,我们要知道,接口的存在是认为它有不同的实现的,可是多数只有一个!并且不断的往里加方法,多了就很难看了。如果不是很简单的应用最好对业务领域建模,并通过service让其对外提供服务。
3、Dao层不要尽量跟业务逻辑相关,dao层的接口一般不同的实现是指jdbc、hibernate、ibatis等。当然不是不可以,我们项目中就跟考虑了业务逻辑。用起来很爽(当然是指扩展、维护性),
我觉得《spring 专业开发指南》这边书写的不错,不仅仅讲spring技术,对这个话题也有所描述。很厚的一本书
1、相对来说service层应该是比较粗的粒度,比如方法都是很多逻辑在里面,以便事务控制。
2、service层很多人理解错(个人认为)。为啥?某service实现类只有一个,我们要知道,接口的存在是认为它有不同的实现的,可是多数只有一个!并且不断的往里加方法,多了就很难看了。如果不是很简单的应用最好对业务领域建模,并通过service让其对外提供服务。
3、Dao层不要尽量跟业务逻辑相关,dao层的接口一般不同的实现是指jdbc、hibernate、ibatis等。当然不是不可以,我们项目中就跟考虑了业务逻辑。用起来很爽(当然是指扩展、维护性),
我觉得《spring 专业开发指南》这边书写的不错,不仅仅讲spring技术,对这个话题也有所描述。很厚的一本书
43 楼
devroller2
2010-11-15
再说说这一点在我们项目中的实践吧,以便大家讨论。我们项目也是按照传统的做法,一个service接口+一个service实现类,结果导致接口的方法不断增加。代码相当难维护。后来我们把一些业务逻辑抽象出来并应用模板方法模式。具体是:
1、关键的service接口只是一个方法,有不同的实现类。
2、有一个默认抽象的实现类,实现模板方法。并有dao的一个属性。
3、dao接口也是只有结果方法。
业务是这样的,我们有不同的业务类型,不同的业务类型有些逻辑不一样,但相同的逻辑是要授权、校验等,并把处理结果保存到数据库。
不同业务类型,从web来的数据被service处理后,保存到db时,对应的表有不一样了,怎么办?我们可以通过注入不同的dao对象就可以实现了。
这个例子是说明当dao实现类不一样的时候service代码如何被复用。
1、关键的service接口只是一个方法,有不同的实现类。
2、有一个默认抽象的实现类,实现模板方法。并有dao的一个属性。
3、dao接口也是只有结果方法。
业务是这样的,我们有不同的业务类型,不同的业务类型有些逻辑不一样,但相同的逻辑是要授权、校验等,并把处理结果保存到数据库。
不同业务类型,从web来的数据被service处理后,保存到db时,对应的表有不一样了,怎么办?我们可以通过注入不同的dao对象就可以实现了。
这个例子是说明当dao实现类不一样的时候service代码如何被复用。
44 楼
helloworldwyn
2010-12-10
个人不太认同service的侵入设计
45 楼
cczakai
2011-03-03
往往设计的时候容易过于追求细节,这样往往是过度设计。
我觉得目前设计模式解决复用性代码的主要模式应该是模板模式。
模板模式要做的是抽离不变部分集成到父类,变化部分由子类完成。
而很多情况,如果因为后续的变化而导致模板不可控的话,从本身来说,不是模板
出了问题,而是缺少对后续变化进行正确评估。
打比方,我们开发版本,一般有基线版本,但基线版本不能解决所有问题,因为每
个地区需求不一样,这样情况提供需要扩展机制,怎么扩展呢?
当我们把不变的解决了,现在就对变进行扩展,怎么去解决这才是核心问题。
如果因为变化,而不断去修改好的代码,导致结果破坏起初的设计意图,变得不可
控制,情况会更糟糕。
对扩展的接口,还要考虑对框架兼容性。扩展的功能,其实也相当添加新的功能,
而这种采用的主要是装饰模式。兼容性没办法解决时候,适当加个适配器。
当把扩展的接口定下来,我们怎么以00思想来处理基线与扩展的关系,扩展必须依
赖基线,就比如hibernate底层还不是用到基线了。这时候,我们需要对基线提供
管理类,扩展通过管理类来访问基线。
管理接口 <>--------------基线接口(模板)----基线实现
| |
| |
| 扩展接口-------Adapter模式------------》框架
| | |
| | |
--------具体扩展实现—————
由于环境,不能上次图片
我觉得目前设计模式解决复用性代码的主要模式应该是模板模式。
模板模式要做的是抽离不变部分集成到父类,变化部分由子类完成。
而很多情况,如果因为后续的变化而导致模板不可控的话,从本身来说,不是模板
出了问题,而是缺少对后续变化进行正确评估。
打比方,我们开发版本,一般有基线版本,但基线版本不能解决所有问题,因为每
个地区需求不一样,这样情况提供需要扩展机制,怎么扩展呢?
当我们把不变的解决了,现在就对变进行扩展,怎么去解决这才是核心问题。
如果因为变化,而不断去修改好的代码,导致结果破坏起初的设计意图,变得不可
控制,情况会更糟糕。
对扩展的接口,还要考虑对框架兼容性。扩展的功能,其实也相当添加新的功能,
而这种采用的主要是装饰模式。兼容性没办法解决时候,适当加个适配器。
当把扩展的接口定下来,我们怎么以00思想来处理基线与扩展的关系,扩展必须依
赖基线,就比如hibernate底层还不是用到基线了。这时候,我们需要对基线提供
管理类,扩展通过管理类来访问基线。
管理接口 <>--------------基线接口(模板)----基线实现
| |
| |
| 扩展接口-------Adapter模式------------》框架
| | |
| | |
--------具体扩展实现—————
由于环境,不能上次图片
46 楼
今日不上网
2011-03-04
skzr.org 写道
我自己就是这样做的,本着dao只做存储的思想
一个service对应N个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); } }
这样貌似查询功能很简单吧。
47 楼
liliugen
2011-04-07
这个帖子还行
48 楼
lijie1819
2011-05-18
看到LZ的设计思想,感觉和抽象工厂模式有点相像。
49 楼
zk7019311
2011-05-26
了解了解。。。。。