我无法决定以下两种模式。保存dataObject(在我的情况下是bean)。这两个选项是:
第一
abstract class DataService {
protected void save(Object data){
//persist the data
}
}
//the service for Project objects
class ProjectService extends DataService {
public void saveProject(Project prj, Object... args /*other save options*/ ){
// some preprocessing, checking, validation
save(prj); //call the method in DataService
// do postprocessing
}
}
//calling save
projectService.saveProjec(project, /*some args*/);
第二
abstract class DataService {
public void save(Object data){
if(beforeSave(data)){
// persist the data
afterSave(data);
}
}
protected boolean beforeSave(){
return true;
}
protected void afterSave(){
}
}
//the service for Project objects
class ProjectService extends DataService {
public initSave(Object... args /*other save options*/ ){
// store these options in class properties
}
@Override
protected bool beforeSave(Project objectAboutToBeSaved){
// some preprocessing, checking, validation
// use class properties set by initSave if needed
return true;//if we want to continue with the saving procedure
}
@Override
protected bool afterSave(Project savedObject){
// do postprocessing
// use class properties set by initSave if needed
}
}
//calling save
projectService.initSave(/*some args*/);
projectService.save(project);
目前我们正在使用第一种模式,但我开始考虑转移到第二种模式,因为:
(PROS)
(CONS)
这个想法来自CakePHP MVC框架,其中模型和控制器都包含这样的回调方法,使用它我可以真正实现一些明确的业务逻辑。
现在我正在使用Java开发 - Spring + Spring Data Graph - (因此是javaish代码),但在我看来,这个问题可能是一个非常通用的问题。
注意:示例是为了保存,但删除过程也是如此。
答案 0 :(得分:4)
另一种解决方案是使用策略模式并执行以下操作。 我们使用该方法进行预先持久化验证,有时甚至计算(基于其他字段)并设置要保留的数据对象的一些字段(例如,我们有一个基于其他更新的“完整”标志每当持久化或更新我们的实体时都会出现字段。)
您的策略:
interface SaveStrategy<T> {
boolean beforeSave(T data);
void afterSave(T data);
}
class SomeFancyProjectSaveStrategy implements SaveStrategy<Project> {
public SomeFancyProjectSaveStrategy( /*parameters*/) {
}
public boolean beforeSave(Project data) {
//whatever you like
}
public void afterSave(Project data) {
//whatever you like
}
}
您的数据服务:
class DataService {
public <T> void save(T data, SaveStrategy<? super T> strategy ){
if(strategy.beforeSave(data)){
// persist the data
strategy.afterSave(data);
}
}
}
然后像这样使用它们:
SaveStrategy<Project> saveStrategy = new SomeFancyProjectSaveStrategy(someParameters); //could reuse that
dataService.save( project, saveStrategy); //the service might even be shared for different data objects
优点:
缺点
答案 1 :(得分:1)
我更喜欢第二个。
主要区别在于它告诉用户该类应该如何使用。这是一个很大的好处(更明确)和一个小的下行(更少的灵活性)。第二种方法也允许更好地扩展子类(ProjectService
的子类可以重用before()
方法并扩展after()
)。要记住的一件事是,子类实际上可以丢弃其中一个方法(通过覆盖它而不是在超类中调用它)。如果允许,请务必记录每个子类。
答案 2 :(得分:1)
第一个例子更简单。如果您需要批量处理数据,第二个示例会更好。即,开始/结束更新的开销很重要。
您仍然可以使用线程本地状态使第二个示例线程安全。
你可以充分利用这两个世界。
bool beforeSave(Project objectAboutToBeSaved);
void saveProject(Project prj, Object... args /*other save options*/ );
bool afterSave(Project savedObject);
这可以用于两种模式。
void saveProject(Project prj, Object... args /*other save options*/ ) {
boolean inBatch = inBatch(prj);
if (!inBatch) beforeSave(prj);
saveProject0(prj, args);
if (!inBatch) afterSave(prj);
}
这允许您混合和匹配并使用一些执行单个更新的方法,但是从某些方法调用时将隐式批处理已保存的数据。
答案 3 :(得分:1)
我不会说。对我来说,两者看起来都不太复杂。
一个简单的CRUD界面应该这样做:
public interface GenericRepository<K extends Serializable, T> {
Collection<T> find();
T find(K id);
K save(T value);
void update(T value);
void delete(T value);
}
在进入持久层之前,所有的验证和检查都应该完成。在我看来,它违反了单一责任原则。
交易属于服务层。持久层无法知道是否要求它参与事务。如果还有其他人怎么办?
你的想法都过于复杂。我拒绝这两个。