一、前言
hi,我是阿昌
,在开发的过程中,不同的人有不同的编码方式和技术阶段,经过日积月累的流逝,就会出现传闻中的“屎山
”代码。
那针对“屎山“的情况,今天就提供几种重复代码的优化思路,具体问题还要看具体场景。
二、正文
1、抽取公共方法
如下代码中,在for循环中无非就是对字符串进行取大小写
1 2 3 4 5 6 7 8 9
| List<String> nameList = Arrays.asList("achang", "Achang", "aChang", "aachang"); for (String name : nameList) { String upperCase = name.toUpperCase(); System.out.println(upperCase); } for (String name : nameList) { String lowerCase = name.toLowerCase(); System.out.println(lowerCase); }
|
那这样子可以认为给一个值然后转变为另一个值的思路进行优化,这里可以用Function接口来优化
1 2 3 4 5 6 7 8 9 10 11
| public static void main(String[] args) { List<String> nameList = Arrays.asList("achang", "Achang", "aChang", "aachang"); parse2Str(nameList, String::toUpperCase,"upperCase"); parse2Str(nameList, String::toLowerCase,"lowerCase"); } public static void parse2Str(List<String> strList, Function<String,String> function,String type){ for (String str : strList) { String result = function.apply(str); System.out.println(result); } }
|
2、抽取工具类
针对相同处理的逻辑,可以抽取工具类的方案;
如下代码,进行判断是否是有效的有效字符串的逻辑;
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| String content = "995931576@qq.com"; Pattern pattern = Pattern.compile("(?:[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*|\"(?:[\\x01-\\x08\\x0b\\x0c\\x0e-\\x1f\\x21\\x23-\\x5b\\x5d-\\x7f]|\\\\[\\x01-\\x09\\x0b\\x0c\\x0e-\\x7f])*\")@(?:(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?|\\[(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?|[a-z0-9-]*[a-z0-9]:(?:[\\x01-\\x08\\x0b\\x0c\\x0e-\\x1f\\x21-\\x5a\\x53-\\x7f]|\\\\[\\x01-\\x09\\x0b\\x0c\\x0e-\\x7f])+)])", Pattern.DOTALL); Matcher matcher = pattern.matcher(content); if (matcher.find()) { String result= matcher.group(); System.out.println(result); }
String content1 = "achang3306@163.com"; Pattern pattern2 = Pattern.compile("(?:[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*|\"(?:[\\x01-\\x08\\x0b\\x0c\\x0e-\\x1f\\x21\\x23-\\x5b\\x5d-\\x7f]|\\\\[\\x01-\\x09\\x0b\\x0c\\x0e-\\x7f])*\")@(?:(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?|\\[(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?|[a-z0-9-]*[a-z0-9]:(?:[\\x01-\\x08\\x0b\\x0c\\x0e-\\x1f\\x21-\\x5a\\x53-\\x7f]|\\\\[\\x01-\\x09\\x0b\\x0c\\x0e-\\x7f])+)])", Pattern.DOTALL); Matcher matcher3 = pattern.matcher(content); if (matcher3.find()) { String result= matcher.group(); System.out.println(result); }
|
那这里就可以帮这一段逻辑抽取成工具类,入参是待判断的邮箱,返回是布尔:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| public static void main(String[] args) { String content = "995931576@qq.com"; System.out.println(predicateEmail(content)); String content1 = "achang3306@163.com"; System.out.println(predicateEmail(content1)); }
public static boolean predicateEmail(String email) { Pattern pattern = Pattern.compile("(?:[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*|\"(?:[\\x01-\\x08\\x0b\\x0c\\x0e-\\x1f\\x21\\x23-\\x5b\\x5d-\\x7f]|\\\\[\\x01-\\x09\\x0b\\x0c\\x0e-\\x7f])*\")@(?:(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?|\\[(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?|[a-z0-9-]*[a-z0-9]:(?:[\\x01-\\x08\\x0b\\x0c\\x0e-\\x1f\\x21-\\x5a\\x53-\\x7f]|\\\\[\\x01-\\x09\\x0b\\x0c\\x0e-\\x7f])+)])", Pattern.DOTALL); Matcher matcher = pattern.matcher(email); boolean result = matcher.find(); if (result) { String str= matcher.group(); System.out.println(str); } return result; }
|
3、模型转换DO<—>DTO
如下,代码需要将UserDO—>UserDTO模型进行转换,这里就会出现set一堆参数属性的代码冗余场景;
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| public static void main(String[] args) { UserDO userDO = new UserDO(); userDO.setId(1L); UserDTO userDTO = new UserDTO(); userDO.setId(userDO.getId()); }
@Data public static class UserDO{ private Long id; } @Data public static class UserDTO{ private Long id; }
|
优化方案有有很多种,这里就例句3种;
4、利用泛型
如下方法基本一致,但是返回的类是不一样的
1 2 3 4 5 6
| public List<UserDTO> getUserDTO(List<UserDO> list){ return list.stream().map(item->new UserDTO()).collect(Collectors.toList()); } public List<UserDO> getUserDO(List<UserDTO> list){ return list.stream().map(item->new UserDO()).collect(Collectors.toList()); }
|
那可以用泛型来优化这段代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| public static <S, T> List<T> convertList(List<S> sourceList, Class<T> targetClass) { return sourceList.stream() .map(item -> createInstance(targetClass)) .collect(Collectors.toList()); }
private static <T> T createInstance(Class<T> clazz) { try { return clazz.getDeclaredConstructor().newInstance(); } catch (Exception e) { throw new RuntimeException("Failed to create instance of " + clazz.getName(), e); } }
public static void main(String[] args) { List<UserDO> userDOS = ...;
List<UserDTO> userDTOS = convertList(userDOS, UserDTO.class);
List<UserDO> userDOSConvertedBack = convertList(userDTOS, UserDO.class); }
|
5、利用继承
比如一个制作咖啡和奶咖啡的代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62
| @Data public class Coffee { protected String name;
public Coffee(String name) { this.name = name; }
public void prepare() { boilWater(); brewCoffeeGrinds(); pourInCup(); addCondiments(); }
protected void boilWater() { System.out.println("Boiling water"); }
protected void brewCoffeeGrinds() { System.out.println("Dripping coffee through filter"); }
protected void pourInCup() { System.out.println("Pouring into cup"); }
protected void addCondiments() { System.out.println("Adding nothing (regular coffee)"); } } @Data public class MilkCoffee { protected String name;
public MilkCoffee(String name) { this.name = name; }
public void prepare() { boilWater(); brewCoffeeGrinds(); pourInCup(); addCondiments(); }
protected void boilWater() { System.out.println("Boiling water"); }
protected void brewCoffeeGrinds() { System.out.println("Dripping coffee through filter"); }
protected void pourInCup() { System.out.println("Pouring into cup"); }
protected void addCondiments() { System.out.println("Adding Milk"); } }
|
如上,只有addCondiments这步是不一样的,其他都是一模一样,这是就可以利用抽象类来优化;
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
| @Data public abstract class Coffee { protected String name;
public Coffee(String name) { this.name = name; }
public void prepare() { boilWater(); brewCoffeeGrinds(); pourInCup(); addCondiments(); }
protected void boilWater() { System.out.println("Boiling water"); }
protected void brewCoffeeGrinds() { System.out.println("Dripping coffee through filter"); }
protected void pourInCup() { System.out.println("Pouring into cup"); }
protected void addCondiments() { System.out.println("Adding nothing (regular coffee)"); } }
|
1 2 3 4 5 6 7 8 9 10
| @Data public class MilkCoffee extends Coffee { public MilkCoffee(String name) { super(name); } @Override protected void addCondiments() { System.out.println("Adding milk"); } }
|
6、利用aop切面
如下代码,每次都要在请求进来进行判断是否有权限
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| @GetMapping("getList/#{userId}") public Map getList(@PathVariable String userId){ User user = getUser(userId); if (user.getRole() != null && !user.getRole().equals("admin")){ throw new RuntimeException("没有权限"); } return new HashMap<>(); }
@GetMapping("save") public void save(){ User user = getUser(userId); if (user.getRole() != null && !user.getRole().equals("admin")){ throw new RuntimeException("没有权限"); } System.out.println("save data"); }
|
那这里就可以使用aop切面,进行一次拦截;
1 2 3 4 5 6 7 8 9 10 11
| @GetMapping("getList/#{userId}") @PermissionAnnotation("getList") public Map getList(@PathVariable String userId){ return new HashMap<>(); }
@GetMapping("save") @PermissionAnnotation("save") public void save(){ System.out.println("save data"); }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| @Component @Aspect public class PermissionAspect { @Before("@annotation(com.achang.springbootmavendemo.annotation.PermissionAnnotation)") public void predicatePermission(PermissionAnnotation permissionAnnotation) throws Throwable { String value = permissionAnnotation.value(); if (User.hasPermission(value)){ throw new RuntimeException("您没有权限"); } }
}
|
1 2 3 4 5 6
| @Documented @Target({ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) public @interface PermissionAnnotation { String value(); }
|