Java 设计模式实战案例

前言

本文将在 Spring / SpringBoot 的基础上,使用策略模式、工厂模式、模板方法模式来优化以下代码,目标是减少 if ... else 判断分支,同时减少判断分支里面的业务代码。为了更好的理解设计模式,下面将给出三个实战案例,循序渐进、由简单到容易地编写案例代码。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public class NoDesignDemo {

public void moreIfElse(String parameter) {
if ("Pepsi".equalsIgnoreCase(parameter)) {
System.out.println("我是百事可乐-初始无设计模式");
} else if ("Coca".equalsIgnoreCase(parameter)) {
System.out.println("我是可口可乐-初始无设计模式");
if ("618".equalsIgnoreCase(parameter)) {
// 需要配合618积分平台大促活动,涉及复杂业务
}
if ("1111".equals(parameter)) {
// 需要配合双11优惠卷平台大促活动,涉及复杂业务
}
} else if ("Wahaha".equalsIgnoreCase(parameter)) {
System.out.println("我是娃哈哈可乐-初始无设计模式");
}
}

public static void main(String[] args) {
new NoDesignDemo().moreIfElse("wahaha");
}

}

利用策略模式优化代码

实现目标

利用策略模式替代每个 if ... else 判断分支里面的业务逻辑,每个策略替代一个判断分支里面的代码,减少代码复杂度。

  • 定义策略接口
1
2
3
4
5
public interface HandlerStrategy {

void getCoca(String parameter);

}
  • 定义百事可乐的策略实现类
1
2
3
4
5
6
7
8
9
@Component
public class PepsiHandler implements HandlerStrategy {

@Override
public void getCoca(String parameter) {
System.out.println("我是百事可乐-策略模式" + parameter);
}

}
  • 定义可口可乐的策略实现类
1
2
3
4
5
6
7
8
9
@Component
public class CocaHandler implements HandlerStrategy {

@Override
public void getCoca(String parameter) {
System.out.println("我是可口可乐-策略模式" + parameter);
}

}
  • 定义娃哈哈可乐的策略实现类
1
2
3
4
5
6
7
8
9
@Component
public class WahahaHandler implements HandlerStrategy {

@Override
public void getCoca(String parameter) {
System.out.println("我是娃哈哈可乐-策略模式" + parameter);
}

}
  • 运行测试代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
public class DesignPatternTest {

/**
* 每个 if ... else 分支里面的业务逻辑都被分工拿走了,这大大降低了 moreIfElse() 里面分支业务逻辑的复杂度
*/
public void moreIfElse(String parameter) {
if ("Pepsi".equalsIgnoreCase(parameter)) {
new PepsiHandler().getCoca(parameter);
} else if ("Coca".equalsIgnoreCase(parameter)) {
new CocaHandler().getCoca(parameter);
} else if ("Wahaha".equalsIgnoreCase(parameter)) {
new WahahaHandler().getCoca(parameter);
}
}

public static void main(String[] args) {
OnlyStrategyTest strategyTest = new OnlyStrategyTest();
strategyTest.more_IfElse("wahaha");
}

}

利用策略、工厂模式优化代码

实现目标

利用策略模式工厂模式完全替代所有 if ... else 判断分支代码。

  • 定义策略接口
1
2
3
4
5
6
7
import org.springframework.beans.factory.InitializingBean;

public interface HandlerStrategyFactory extends InitializingBean {

void getCoca(String parameter);

}
  • 定义百事可乐的策略实现类
1
2
3
4
5
6
7
8
9
10
11
12
13
14
@Component
public class PepsiHandler implements HandlerStrategyFactory {

@Override
public void getCoca(String parameter) {
System.out.println("我是百事可乐-策略模式+工厂模式" + parameter);
}

@Override
public void afterPropertiesSet() throws Exception {
Factory.register("Pepsi", this);
}

}
  • 定义可口可乐的策略实现类
1
2
3
4
5
6
7
8
9
10
11
12
13
14
@Component
public class CocaHandler implements HandlerStrategyFactory {

@Override
public void getCoca(String parameter) {
System.out.println("我是可口可乐-策略模式+工厂模式" + parameter);
}

@Override
public void afterPropertiesSet() throws Exception {
Factory.register("Coca", this);
}

}
  • 定义娃哈哈可乐的策略实现类
1
2
3
4
5
6
7
8
9
10
11
12
13
14
@Component
public class WahahaHandler implements HandlerStrategyFactory {

@Override
public void getCoca(String parameter) {
System.out.println("我是娃哈哈可乐-策略模式+工厂模式" + parameter);
}

@Override
public void afterPropertiesSet() throws Exception {
Factory.register("Wahaha", this);
}

}
  • 定义工厂类
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public class Factory {

// 定义策略的Map缓存
private static Map<String, HandlerStrategyFactory> strategyMap = new ConcurrentHashMap<>();

public static HandlerStrategyFactory getInvokeStrategy(String name) {
return strategyMap.get(name);
}

public static void register(String name, HandlerStrategyFactory handler) {
if (null == name || null == handler) {
return;
}
strategyMap.put(name, handler);
}

}
  • 运行测试代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
@SpringBootTest
public class DesignPatternTest {

/**
* 完全替代所有 if ... else 分支代码
*/
public void moreIfElse(String parameter) {
HandlerStrategyFactory invokeStrategy = Factory.getInvokeStrategy(parameter);
invokeStrategy.getCoca(parameter);
}

@Test
public void run() {
moreIfElse("Coca");
}

}

利用策略、工厂、模板方法模式优化代码

实现目标

利用策略模式工厂模式模板方法模式完全替代所有 if ... else 判断分支代码。

  • 定义策略模板抽象类
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
import org.springframework.beans.factory.InitializingBean;

public abstract class AbstractColaHandler implements InitializingBean {

public void getCoca(String parameter) {
throw new UnsupportedOperationException();
}

// 模板方法1,按照业务可口可乐自己单独实现
public String cocaMethod(String name) {
throw new UnsupportedOperationException();
}

// 模板方法2,按照业务百事可乐自己单独实现
public String pepsiMethod(String name) {
throw new UnsupportedOperationException();
}

// 模板方法3,按照业务娃哈哈可乐自己单独实现
public String wahahaMethod(String name) {
throw new UnsupportedOperationException();
}

protected void initResource() {
System.out.println("本方法抽象父类已经统一实现,为了方便扩展,子类也可以重写");
}

// 留给子类实现
public abstract String invokeCommon();

}
  • 定义百事可乐的模板方法子类
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
@Component
public class PepsiHandler extends AbstractColaHandler {

@Override
public void getCoca(String parameter) {
System.out.println("我是百事可乐-策略+工厂+模板方法" + parameter);
}

@Override
public String pepsiMethod(String name) {
return "调用百事可乐独有的 pepsiMethod() 方法";
}

@Override
public String invokeCommon() {
return "我是百事可乐";
}

@Override
public void afterPropertiesSet() throws Exception {
Factory.register("Pepsi", this);
}

}
  • 定义可口可乐的模板方法子类
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
@Component
public class CocaHandler extends AbstractColaHandler {

@Override
public void getCoca(String parameter) {
System.out.println("我是可口可乐-策略+工厂+模板方法" + parameter);
}

@Override
public String cocaMethod(String name) {
return "调用可口可乐独有的 cocaMethod() 方法";
}

@Override
public String invokeCommon() {
return "我是可口可乐";
}

@Override
public void afterPropertiesSet() throws Exception {
Factory.register("Coca", this);
}

}
  • 定义娃哈哈可乐的模板方法子类
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
@Component
public class WahahaHandler extends AbstractColaHandler {

@Override
public void getCoca(String parameter) {
System.out.println("我是娃哈哈可乐-策略+工厂+模板方法" + parameter);
}

@Override
public String wahahaMethod(String name) {
return "调用娃哈哈可乐独有的 wahahaMethod() 方法";
}

@Override
public String invokeCommon() {
return "我是娃哈哈可乐";
}

@Override
public void afterPropertiesSet() throws Exception {
Factory.register("Wahaha", this);
}

}
  • 定义工厂类
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public class Factory {

// 定义策略的Map缓存
private static Map<String, AbstractColaHandler> strategyMap = new ConcurrentHashMap<>();


public static AbstractColaHandler getInvokeStrategy(String str) {
return strategyMap.get(str);
}

public static void register(String str, AbstractColaHandler handler) {
if (null == str || null == handler) {
return;
}
strategyMap.put(str, handler);
}

}
  • 运行测试代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
@SpringBootTest
public class DesignPatternTest {

/**
* 完全替代所有 if ... else 分支代码
*/
public static void moreIfElse(String parameter) {
AbstractColaHandler invokeStrategy = Factory.getInvokeStrategy(parameter);
invokeStrategy.getCoca(parameter);
}

@Test
public void run() {
moreIfElse("Coca");
}

}

参考资料