谢邀先来简单粗暴的。。。。竟然想把两个方法合一,很简单,其实合一的时候,就是把公共部分用同一个东西表示,楼上已有兄弟有建议用接口,是可以的,不过竟然属性和代码结构差不多,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<Client> retrieveEntityRecords(RequestParam request) { List<Client> result = LocationIdsQueryUtils.doQuery(clientRepository, request); return result; } 大体就是这样,仅供参考,就酱