行为参数化实践
一.背景
最近公司在搞代码优化,场景如下:原有代码中存在两个不同的实体,但是实体中存在一部分相同属性和一部分不同的属性,目前对这两个实体的操作有百分之八十逻辑是相同的,只有少部分内部逻辑是不同的,但是少部分的逻辑所起的作用是相同的。目前代码写了两份相同逻辑的代码,导致代码不复用,后续不利于维护,修改功能可能需要重复修改。
二.过程(伪代码描述实现过程)
2.1 定义基类
既然两个实体存在许多共有属性,能想到的就是定义一个基类,当然这里只存在一个共有属性name;
package com.ljm.function;
public class Basic {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
2.2 定义子类
package com.ljm.function;
public class AddressBasic extends Basic{
private String address;
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
@Override
public String toString() {
return "AddressBasic{" +
"address='" + address + '\'' +
'}';
}
}
package com.ljm.function;
public class TrainBasic extends Basic{
private String trainNo;
public String getTrainNo() {
return trainNo;
}
public void setTrainNo(String trainNo) {
this.trainNo = trainNo;
}
@Override
public String toString() {
return "TrainBasic{" +
"trainNo='" + trainNo + '\'' +
'}';
}
}
2.3 定义接口
既然存在相同的功能,但是内部逻辑不同,那么自然而然能想到的就是定义一个接口。
package com.ljm.function;
import java.util.List;
public interface IBasic<T extends Basic> {
List<T> filter(List<T> basicList,String accept);
}
2.4 定义AddressBasicImpl
package com.ljm.function;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;
public class AddressBasicImpl implements IBasic<AddressBasic> {
@Override
public List<AddressBasic> filter(List<AddressBasic> basicList, String accept) {
if (basicList == null) {
return new ArrayList<>();
}
return basicList.stream().filter(o -> Objects.equals(o.getAddress(), accept)).collect(Collectors.toList());
}
}
AddressBasicImpl做的事情其实很简单,就是对满足指定条件的地址过滤.所写皆为伪代码,未引入工具类,所以看上去不是很优雅.
2.5定义TrainBasicImpl
package com.ljm.function;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;
public class TrainBasicImpl implements IBasic<TrainBasic>{
@Override
public List<TrainBasic> filter(List<TrainBasic> basicList,String accept) {
if(basicList==null){
return new ArrayList<>();
}
return basicList.stream().filter(o-> Objects.equals(o.getTrainNo(),accept)).collect(Collectors.toList());
}
}
TrainBasicImpl-做的事情其实很简单,就是对满足指定条件的车次号过滤.
2.6 测试
package com.ljm.function;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class TestBasic {
public static void main(String[] args) {
List<AddressBasic> addressList=new ArrayList<>();
List<TrainBasic> trainList=new ArrayList<>();
for (int i = 0; i < 5; i++) {
AddressBasic addressBasic = new AddressBasic();
addressBasic.setName("江西");
addressBasic.setAddress("上饶"+i);
addressList.add(addressBasic);
}
for (int i = 0; i < 5; i++) {
TrainBasic trainBasic = new TrainBasic();
trainBasic.setName("火车");
trainBasic.setTrainNo("G1679"+i);
trainList.add(trainBasic);
}
TestBasic testBasic = new TestBasic();
IBasic<AddressBasic> addressBasicImpl= new AddressBasicImpl();
IBasic<TrainBasic> trainBasicImpl=new TrainBasicImpl();
System.out.println(Arrays.toString(testBasic.filterByCondition(addressList, "上饶2", addressBasicImpl).toArray()));
System.out.println(Arrays.toString(testBasic.filterByCondition(trainList, "G16792", trainBasicImpl).toArray()));
}
private <T> List<T> filterByCondition(List<T> dataList, String condition, IBasic iBasic){
return iBasic.filter(dataList,condition);
}
}
由上面测试,可以看出,addressBasicImpl过滤的是满足上饶2条件的集合,而trainBasicImpl过滤的是满足G16792条件的集合,然后定义了一个泛型方法,传入了不同的实现,利用了java多态的特性,传入指定的子类实现.
三.总结
其实,上述操作,利用了java的继承,多态的特性来使代码变得更加的易复用,易扩展,最主要的是将实现当作参数传入的方法中,然后在方法中调用各自的实现,由于公司的业务代码中存在多个接口,所以不能定义成函数式接口,定义成函数接口,我们就不用特地的去创建两个类,可以利用lambada的方式直接将实现传入到方法中,但是如果实现比较复杂的话,还是推荐创建类,便于后期维护,不然代码都堆积在一起,后面可能自己看都不知道怎么回事了。