谢邀先来简单粗暴的。。。。竟然想把两个方法合一,很简单,其实合一的时候,就是把公共部分用同一个东西表示,楼上已有兄弟有建议用接口,是可以的,不过竟然属性和代码结构差不多,lambda+泛型应该就可以解决
我们可以看到,那两个方法,需要归一的地方就两个
customer.getDone()和client.getDone()
customer.setLocation("hongkong")和client.setLocation("hongkong")
这两个地方的对应的方法分别就应该是Predicate和Consumer了,所以我们可以建立这么一个公共方法execute
public <T> void execute(T t, Predicate<T> donePredicate, Consumer<T> locationConsumer){
if(donePredicate.test(t)){
locationConsumer.accept(t);
}
System.out.println("result: "+ t);
}
所以之前的两个方法execute_customer和execute_client就可以改为
public void execute_customer(Customer customer){
this.execute(customer, Customer::getDone, c -> c.setLocation("hongkong"));
}public void execute_client(Client client){
this.execute(client, Client::getDone, c -> c.setLocation("hongkong"));
}
不过不建议你这么写。。。毕竟三个参数的方法,还是很长了。。。并且Customer和Client在业务上本身可能也没有啥联系,强行整合代码,只会给以后的维护带来巨大理解成本,因为它们只是恰好有两个相同的字段,恰好他们的处理模式一样
但是我们可以换个角度思考,既然恰好它们有两个相同的字段,恰好他们处理模式一样,题主也想把他们合在一个方法里,那我们不看Customer和Client,光看属性location和isDone,光看方法里if的处理,是不是就可以说明,他们两个属性合在一起代表着一个业务,一个独立于Customer和Client的业务,它有自己的属性location和isDone,也有自己的行为,那就是if的处理,假如我们设定这么一个业务叫Location,那它一定可以写成
public class Location {
private String location;
private Boolean isDone;
// get set toString ... public void execute(){
if(this.getDone()){
this.setLocation("hongkong");
}
}
}
这样的话,Customer和Client就变成
public class Customer {
private Location location;
}public class Client {
private Location location;
}
因此Order里的方法就变成
public void execute_customer(Customer customer){
customer.getLocation().execute();
}public void execute_client(Client client){
client.getLocation().execute();
}
嗯嗯,这么写,赶脚完美的雅痞,当然一切还是以实际业务来决定,我只是根据当前题主提供的信息做了一些猜想,并且写出的一种方式,实际业务可能需要调整,仅供参考,就酱
===============================小小更新==============================
评论里题主提到如何用接口来整合,其实这也是面向接口编程的小实例哈,面向接口编程,就是需要把整个业务逻辑按照接口预定义的方式组装起来,出现接口的调用的地方,即业务抽象的点
其实和之前的抽象点差不多,还是
customer.getDone()和client.getDone()
customer.setLocation("hongkong")和client.setLocation("hongkong")
这两个点之前用函数式接口表示的,此时用接口去表示,比如我们定义这样一个功能接口,就叫ILocation吧,那它可以这么表示
public interface ILocation{
Boolean getDone();
void setLocation(String location);
}
为什么要这么写,是恰好,这两个方法的命名方式就是Client和Customer中的属性set,get方法,这样就减少了写实现方法的必要,之后Client和Customer就可以这么表示
@Getter
@Setter
public class Client implements ILocation{
private String location;
private Boolean isDone;
}@Getter
@Setter
public class Customer implements ILocation{
private String location;
private Boolean isDone;
}
因为set和get方法方法都已经实现了ILocation,用了lombok的注解后,代码可以啥都不加了(lombok对于默认的Boolean类型属性的get方法是getIsDone,所以若是需要的话,不要加is开头)
之后在Order那里就可以这么写一个公用方法
public void execute(ILocation location){
if(location.getDone()){
location.setLocation("hongkong");
}
}
接口实现大体就是这样,仅供参考,就酱
=============================2018-11-21新问题更新===============================回答问题之前,还是要说明一点哈,任何代码的整合,要么是要在业务范围内可以合并,要么就是公共结构或工具抽取,过分强行的整合代码,只会胡乱增加业务之间的耦合,给后续扩展开发带来极大的不变
回到题主的新问题中,可以看到,这个时候已经不是简单靠传入参数就解决了(虽然也还是可以,不过那么写实在不太友好,也不利于扩展),这次我们可以从直接两段方法中简单抽象出这么一个业务过程
public <T> List<T> retrieveEntityRecords(RequestParam request) { List<String> ids = request.getId();
String location = request.getLocation();
boolean idsCk = CollectionUtils.isNotEmpty(ids) && ids.size() > 0;
boolean locationCk = !StringUtils.isEmpty(location);
List<T> result;
try {
if (idsCk) {
if (locationCk) {
// use [ids location] query db
} else {
// use [ids] query db
}
} else {
if (locationCk) {
// use [location] query db
} else {
// query all record in db
}
}
} catch (Exception e) {
throw new SystemException();
}
return result;
}
以上这段代码应该就是之前两个方法的主干代码了,也是这次要整合的业务核心代码,我们还是学上个问题一样,把公共部分抽离处理啊,其他需要具体实现的那就用接口来实现了,那具体需要实现的就是这4行注释了
// use [ids location] query db
// use [ids] query db
// use [location] query db
// query all record in db
那所以我们定义这么一个接口ILocationIdsQuery(个人理解就是按照Location和id进行查询的公共逻辑,所以这么简单取名了),它就定义有这么4个抽象方法
public interface ILocationIdsQuery<T> {
List<T> queryByIdsAndLocation(List<String> ids, String location);
List<T> queryByIds(List<String> ids);
List<T> queryLocation(String location);
List<T> query();
}
这么定义下来,就会发现其实这和customerRepository和clientRepository的接口方法一致,如果你的customerRepository和clientRepository没有公共的父类接口,那么这个时候你可以给它们都加个一个父类接口ILocationIdsQueryExecutor,并补充他们的实现,如果本身customerRepository和clientRepository就有这么一个公共的父类接口,那就可以不用定义这么一个新接口了
有了这么一个公共接口之后,那就简单了,直接开一个工具类LocationIdsQueryUtils(保持业务的一致性,方便其他人看看代码,所以就取了这么一个名字)
public class LocationIdsQueryUtils {public static <T> List<T> doQuery(ILocationIdsQuery<T> locationIdsQuery, RequestParam request){
List<String> ids = request.getId();
String location = request.getLocation();
boolean idsCk = CollectionUtils.isNotEmpty(ids) && ids.size() > 0;
boolean locationCk = !StringUtils.isEmpty(location);
List<T> result;
try {
if (idsCk) {
if (locationCk) {
// use [ids location] query db
result = locationIdsQuery.queryByIdsAndLocation(ids, location);
} else {
// use [ids] query db
result = locationIdsQuery.queryByIds(ids);
}
} else {
if (locationCk) {
// use [location] query db
result = locationIdsQuery.queryByLocation(location);
} else {
// query all record in db
result = locationIdsQuery.queryAll();
}
}
} catch (Exception e) {
throw new SystemException();
}
return result;
}
}
那有了这么一个工具类,剩下的就好写多了,直接调用工具类即可
public List<Customer> retrieveEntityRecords(RequestParam request) {
List<Customer> result = LocationIdsQueryUtils.doQuery(customerRepository, request);
return result;
}public List retrieveEntityRecords(RequestParam request) {
List result = LocationIdsQueryUtils.doQuery(clientRepository, request);
return result;
}
大体就是这样,仅供参考,就酱