java代码优化

 public SomeDTO toDTO(String type){
        if ("A".equals(type)){
            SomeDTO someDTO = new SomeDTO();
            //todo查表A结果set到dto
            someDTO.setA("xxxx");
            return someDTO;
        }else if ("B".equals(type)){
            SomeDTO someDTO = new SomeDTO();
            //todo查表B
            someDTO.setB("xxxx");
            return someDTO;
        }else if ("C".equals(type)){
            SomeDTO someDTO = new SomeDTO();
            //todo查表A结果set到dto
            someDTO.setA("xxxx");
            //todo查表B结果set到dto
            someDTO.setB("xxxx");
            return someDTO;
            //省略很多if及代码
        }else{
            //........
        }

像这种有什么比较优雅的方式可以优化下if else?

阅读 4k
6 个回答

其实还是策略模式,不过不走接口了,直接上枚举

/**
 * @author wyh
 * @date 2021/11/3 19:21
 */
@AllArgsConstructor
@Getter
public enum SetterEnum {

    A("typeA") {
        @Override
        void setV(SomeDTO someDTO, Supplier<?> supplier) {
            someDTO.setA(supplier.get());
        }
    }, B("typeB") {
        @Override
        void setV(SomeDTO someDTO, Supplier<?> supplier) {
            someDTO.setB(supplier.get());
        }
    },C("typeC") {
        @Override
        void setV(SomeDTO someDTO, Supplier<?> supplier) {
            someDTO.setC(supplier.get());
        }
    };

    private final String type;

    /**
     * 设置值
     *
     * @param someDTO  需要设值的对象
     * @param supplier 查询动作,用到type可换为function
     */
    abstract void setV(SomeDTO someDTO, Supplier<?> supplier);

    /**
     * 根据枚举值获取枚举
     */
    public static SetterEnum typeOf(String type) {
        SetterEnum[] values = SetterEnum.values();
        return Stream.of(values)
                .filter(v -> Objects.equals(v.getType(), type)).findFirst()
                .orElse(null);
    }

    public static void main(String[] args) {
        SomeDTO my = new SomeDTO();
        SetterEnum.typeOf("typeA").setV(my, () -> userMapper.selectByType(1));
    }
}

以下代码只是示意,提前做好 type 跟行为的映射,然后查表

    private Map<String, Supplier<SomeDTO>> suppliers = new HashMap<>();

    private void initConsumers() {
        suppliers.put("A", () -> {
            SomeDTO someDTO = new SomeDTO();
            // todo查表A结果set到dto
            someDTO.setA("xxxx");
            return someDTO;
        });

        suppliers.put("B", () -> {
            SomeDTO someDTO = new SomeDTO();
            // TOOD 查表B结果set到dto
            return someDTO;
        });

        suppliers.put("C", () -> {
            SomeDTO someDTO = new SomeDTO();
            // TODO 查表C结果set到dto   
            return someDTO;
        });
    }

    public SomeDTO toDTO(String type){
        Supplier<SomeDTO> supplier = suppliers.get(type);
        if (supplier != null) {
            return supplier.get();
        } else {
            // ......
        }
    }

不过观察下来,其实每个动作都要创建 SomeDTO 对象,所以不如把这个放外面,Lambda 只是对其进行设置。把 Supplier 形式改为 Consumer 形式:

    private Map<String, Consumer<SomeDTO>> consumers = new HashMap<>();

    private void initConsumers() {
        consumers.put("A", (SomeDTO someDTO) -> {
            // todo查表A结果set到dto
            someDTO.setA("xxxx");
        });

        consumers.put("B", (SomeDTO someDTO) -> {
            // TOOD 查表B结果set到dto
        });

        consumers.put("C", (SomeDTO someDTO) -> {
            // TODO 查表C结果set到dto
        });
    }

    public SomeDTO toDTO(String type) {
        Consumer<SomeDTO> supplier = consumers.get(type);
        SomeDTO someDTO = new SomeDTO();
        if (supplier != null) {
            supplier.accept(someDTO);;
        } else {
            // ......
        }
        return someDTO;
    }

如果各个行为之间代码不少是相同的,那可以进一步优化,在 initConsumers 中把可重用的地方提取出来

    private void initConsumers() {
        Consumer<SomeDTO> aConsumer = (dto) -> dto.setA("a");
        Consumer<SomeDTO> bConsumer = (dto) -> dto.setB("b");

        consumers.put("A", aConsumer);
        consumers.put("B", bConsumer);

        consumers.put("C", (SomeDTO someDTO) -> {
            aConsumer.accept(someDTO);
            bConsumer.accept(someDTO);
        });
    }

工厂模式和策略模式,都是可以做到消除if else的

Strategy Pattern + Spring Ioc

public interface ISetter<T> {
    T setVal();
}
@Component("A")
public class ASetter implements ISetter<SomeDTO> {
    @Override
    public SomeDTO setVal() {
        return new SomeDTO().setA("A");
    }
}

@Component("B")
public class BSetter implements ISetter<SomeDTO>{
    @Override
    public SomeDTO setVal() {
        return new SomeDTO().setA("B").setC("C");
    }
}
@Resource
private Map<String, ISetter<SomeDTO>> beans;

@Test
public void testSetter() {
    System.out.println(beans.get("B").setVal());
}

枚举 + 策略模式,然后根据映射来选择,简单就是写个map映射 找不同的set

可以用反射

    SomeDTO someDTO = new SomeDTO();
    Class<? extends SomeDTO> aClass = someDTO.getClass();
    // 获得私有变量
    Field field = aClass.getDeclaredField(type);
    field.setAccessible(true); // 开启访问私有变量,如果不设置会抛异常
    Class<?> typeClass = field.getType();
    Constructor<?> constructor = typeClass.getConstructor(typeClass);
    field.set(someDTO, constructor.newInstance("xxx")); // 赋值
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题