if-else,这是个再正常不过的coding习惯,当我们代码量小的时候用来做条件判断是再简单不过的了。但对于优秀程序员来说,这却不是好代码。不信你往下看…
1. 卫语句提前return
假设有如下代码 - if (condition) {
- // do something
- } else {
- return xxx;
- }
[color=rgb(51, 102, 153) !important]复制代码
通过对判断条件取反,代码在逻辑表达上会更加清晰
- if (!condition) {
- return xxx;
- }
- // do something
[color=rgb(51, 102, 153) !important]复制代码
2. 使用Optional简化if判空
2.1 简化1级判空
假设有如下代码 - if (input != null) {
- // return value 1
- } else {
- // return value 2
- }
[color=rgb(51, 102, 153) !important]复制代码
使用Optional后 - return Optional.ofNullable(input).map(value1).orElse(value2);
[color=rgb(51, 102, 153) !important]复制代码
2.2 简化多级判空假设有如下代码 - if (input != null && input.getUser() != null && input.getUser().getName() != null) {
- // do action 1
- } else {
- // do action 2
- }
[color=rgb(51, 102, 153) !important]复制代码
使用Optional后 - Optional.ofNullable(input)
- .map(Input::getUser)
- .map(User::getName)
- .map(action1)
- .orElse(action2);
[color=rgb(51, 102, 153) !important]复制代码
对于没有else的场景,使用ifPresent即可 - if (input != null && input.getUser() != null && input.getUser.getName() != null) {
- // do action
- }
[color=rgb(51, 102, 153) !important]复制代码
- Optional.ofNullable(input)
- .map(Input::getUser)
- .map(User::getName)
- .ifPresent(action);
[color=rgb(51, 102, 153) !important]复制代码
3. 策略模式
假设有如下代码: - if ("dog".equals(petType)) {
- // 处理dog
- } else if ("cat".equals(petType)) {
- // 处理cat
- } else if ("pig".equals(petType)) {
- // 处理pig
- } else if ("rabbit".equals(petType)) {
- // 处理rabbit
- } else {
- throw new UnsupportedOperationException();
[color=rgb(51, 102, 153) !important]复制代码
这就是不要根据不同的参数类型走不同的代码逻辑,这种场景很常见,他还会以switch-case的方式出现: - switch (petType) {
- case "dog":
- // 处理dog
- break;
- case "cat":
- // 处理cat
- break;
- case "pig":
- // 处理pig
- break;
- case "rabbit":
- // 处理rabbit
- break;
- default:
- throw new UnsupportedOperationException();
- }
[color=rgb(51, 102, 153) !important]复制代码
不同的代码逻辑就代表了不同的策略,我们可以通过如下几个方式改写。
3.1 多态- public interface Strategy {
- void invoke(); // 处理各个逻辑
- }
[color=rgb(51, 102, 153) !important]复制代码
- public class DogStrategy implements Strategy {
- @Override
- public void invoke() {
- // 处理dog
- }
- }
[color=rgb(51, 102, 153) !important]复制代码
- public class CatStrategy implements Strategy {
- @Override
- public void invoke() {
- // 处理cat
- }
- }
[color=rgb(51, 102, 153) !important]复制代码
- public class PigStrategy implements Strategy {
- @Override
- public void invoke() {
- // 处理pig
- }
- }
[color=rgb(51, 102, 153) !important]复制代码
- public class RabbitStrategy implements Strategy {
- @Override
- public void invoke() {
- // 处理rabbit
- }
- }
[color=rgb(51, 102, 153) !important]复制代码
具体的策略对象可以放在一个Map中,优化后的实现类似如下 - Strategy strategy = map.get(petType);
- stratefy.invoke();
[color=rgb(51, 102, 153) !important]复制代码
关于如何存放到Map中也两个可以参考的方式。
3.1.1 静态表
- Map<String, Strategy> map = ImmutableMap.<String, Strategy>builder()
- .put("dog", new DogStrategy())
- .put("cat", new CatStrategy())
- .put("pig", new PigStrategy())
- .put("rabbit", new RabbitStrategy())
- .build();
[color=rgb(51, 102, 153) !important]复制代码
3.1.2 Spring托管下的动态注册定义一个注册中心用于接受注册信息 - public enum StrategyMapping {
- INSTANCE;
- private final Map<String, Class<? extends Strategy>> map = new ConcurrentHashMap<>();
- public void register(String type, Class<? extends Strategy> clazz) {
- map.put(type, clazz);
- }
- public Strategy getStrategy(String type) {
- Class<? extends Strategy> clazz = map.get(type);
- if (clazz == null) {
- throw new UnregisteredException();
- }
- return SpringContextHolder.getBean(clazz);
- }
- }
[color=rgb(51, 102, 153) !important]复制代码
将每个Strategy交由Spring管理,并在构造后注册 - @Component
- public class DogStrategy implements Strategy {
- @PostConstruct
- public void init() {
- StrategyMapping.INSTANCE.register("dog", this.getClass());
- }
- @Override
- public void invoke() {
- // 处理dog
- }
- }
[color=rgb(51, 102, 153) !important]复制代码
使用方式就变成了 - Strategy strategy = StrategyMapping.INSTANCE.getStrategy(petType);
- stratefy.invoke();
[color=rgb(51, 102, 153) !important]复制代码
3.2 枚举采用多态会额外产生很多策略类,如果我们已经预先将petType定义成了枚举,就会发现可以把Strategy中的invoke()方法放到枚举中,从而完成了一种映射关系。 - public enum PetType {
- DOG {
- @Override
- public void invoke() {
- // 处理dog
- }
- },
- CAT {
- @Override
- public void invoke() {
- // 处理cat
- }
- },
- PIG {
- @Override
- public void invoke() {
- // 处理pig
- }
- },
- RABBIT {
- @Override
- public void invoke() {
- // 处理rabbit
- }
- };
- public abstract void invoke();
- }
[color=rgb(51, 102, 153) !important]复制代码
这样在调用时的代码就类似如下: - PetType petType = PetType.valueOf(type.toUpperCase(Locale.ROOT));
- petType.invoke();
[color=rgb(51, 102, 153) !important]复制代码
3.3 函数式简化策略同样面对多态会额外产生很多策略类的问题,除了枚举我们还可以使用函数式的方式来改写,这里有个前提最好是策略的内容不会过于复杂,不然在代码的可读性上会比较差。同样我们会有一个map静态表,不过map里面存放的是lambda - Map<String, Runnable> map = ImmutableMap.<String, Runnable>builder()
- .put("dog", () -> {
- // 处理dog
- })
- .put("cat", () -> {
- // 处理cat
- })
- .put("pig", () -> {
- // 处理pig
- })
- .put("rabbit", () -> {
- // 处理rabbit
- })
- .build();
[color=rgb(51, 102, 153) !important]复制代码
使用方式则变成了 - Runnable task = map.get(petType);
- task.run();
|