【阿昌之丑陋代码优化】重复代码优化方案

一、前言

在开发的过程中,不同的人有不同的编码方式和技术阶段,经过日积月累的流逝,就会出现传闻中的“屎山”代码。
那阿昌“屎山“中有重复代码的问题,那今天就提供几种重复代码的优化思路,具体问题还要看具体场景。

二、正文

1、抽取公共方法

如下代码中,在for循环中无非就是对字符串进行取大小写

		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接口来优化

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、抽取工具类

针对相同处理的逻辑,可以抽取工具类的方案;

如下代码,进行判断是否是有效的有效字符串的逻辑;

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);
}

那这里就可以帮这一段逻辑抽取成工具类,入参是待判断的邮箱,返回是布尔:

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一堆参数属性的代码冗余场景;

	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种;

  • 采用现成的框架进行,如mapstruct

  • 采用序列化复制,如ali的fastjson,这两类都需要implements Serializable

    JSON.parseObject(JSON.toJSONString(userDO),UserDTO.class)
    
  • 采用java反射,如beanCopy

    BeanUtil.copyProperties(userDO,new UserDTO());
    

4、利用泛型

如下方法基本一致,但是返回的类是不一样的

	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());
	}

那可以用泛型来优化这段代码:

// 泛型方法,用于转换列表
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 = ...; 

  // 转换 UserDO 到 UserDTO
  List<UserDTO> userDTOS = convertList(userDOS, UserDTO.class);

  // 转换 UserDTO 到 UserDO
  List<UserDO> userDOSConvertedBack = convertList(userDTOS, UserDO.class);
}

5、利用继承

比如一个制作咖啡和奶咖啡的代码:

@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这步是不一样的,其他都是一模一样,这是就可以利用抽象类来优化;

@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)");
    }
}

@Data
public class MilkCoffee extends Coffee {
    public MilkCoffee(String name) {
        super(name);
    }
    @Override
    protected void addCondiments() {
        System.out.println("Adding milk");
    }
}

6、利用aop切面

如下代码,每次都要在请求进来进行判断是否有权限

	@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切面,进行一次拦截;

	@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");
	}
@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("您没有权限");
    }
  }

}
@Documented
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface PermissionAnnotation {
  String value();
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

阿昌喜欢吃黄桃

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值