在写业务代码的时候发现需要大量使用If,同时里面还写满了业务逻辑代码。为了使代码更加简洁一些,使用设计模式把原有If或者Switch简化。

本篇博客参考了(对二者结合整理):

一、策略模式

需求:虚拟一个业务需求,让大家容易理解。假设有一个订单系统,里面的一个概念是根据订单的不同类型做出不同的处理。

image-20211122104709271

AOrderTypeHandler

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
package com.oy.test.handler;

import com.oy.test.bean.OrderDTO;

/**
* 订单类型处理定义
* 使用抽象类,那么子类就只有一个继承了
*/
public abstract class AOrderTypeHandler {

/**
* 一个订单类型做一件事
*
* @param dto 订单实体
* @return 为了简单,返回字符串
*/
abstract public String handler(OrderDTO dto);

}

HandlerContext

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
package com.oy.test.handler;

import java.util.Map;

/**
* 订单策略模式环境
* 这个类的注入由HandlerProccessor实现
*/
public class HandlerContext {
private Map<String, AOrderTypeHandler> handlerMap;

/**
* 构造传参不能直接使用注解扫入
*/
public HandlerContext(Map<String, AOrderTypeHandler> handlerMap) {
this.handlerMap = handlerMap;
}

/**
* 获得实例
*
* @param type
* @return
*/
public AOrderTypeHandler getInstance(String type) {
if (type == null) {
throw new IllegalArgumentException("type参数不能为空");
}
AOrderTypeHandler clazz = handlerMap.get(type);
if (clazz == null) {
throw new IllegalArgumentException("该类型没有在枚举OrderTypeHandlerAnno中定义,请定义:" + type);
}
return clazz;
}

}

HandlerProccessor

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
package com.oy.test.handler;

import com.oy.test.common.OrderTypeEnum;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.stereotype.Component;
import org.springframework.util.ObjectUtils;

import java.util.Collection;
import java.util.HashMap;
import java.util.Map;

/**
* 策略模式,处理type与实现类的映射关系
*/
@Component
public class HandlerProccessor implements BeanFactoryPostProcessor {

/**
* 扫描@OrderTypeHandlerAnno注解,初始化HandlerContext,将其注册到spring容器
*
* @param beanFactory bean工厂
* @throws BeansException
*/
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
Map<String, AOrderTypeHandler> handlerMap = new HashMap<>();
for (OrderTypeEnum temp : OrderTypeEnum.values()) {
AOrderTypeHandler beanInstacle = getBeansWithAnnotation(beanFactory, AOrderTypeHandler.class, OrderTypeHandlerAnno.class, temp.getCode());
handlerMap.put(temp.getCode(), beanInstacle);
}
HandlerContext context = new HandlerContext(handlerMap);
//单例注入
beanFactory.registerSingleton(HandlerContext.class.getName(), context);
}

/*
* 通过父类+注解找到实体类
*/
private <T> T getBeansWithAnnotation(ConfigurableListableBeanFactory beanFactory, Class<T> manager, Class<? extends OrderTypeHandlerAnno> annotation, String code) throws BeansException {
if (ObjectUtils.isEmpty(code)) {
throw new RuntimeException("code is null ");
}
Collection<T> tCollection = beanFactory.getBeansOfType(manager).values();
for (T t : tCollection) {
OrderTypeHandlerAnno orderTypeHandlerAnno = t.getClass().getAnnotation(annotation);
if (ObjectUtils.isEmpty(orderTypeHandlerAnno)) {
throw new RuntimeException("该注解没有写入值 :" + code);
}
//注解值是否与code相等
if (code.equals(orderTypeHandlerAnno.value().getCode())) {
return t;
}
}
throw new RuntimeException("通过code没有找到该注解对应的实体类 :" + code);
}

}

OrderTypeHandlerAnno

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
package com.oy.test.handler;

import com.oy.test.common.OrderTypeEnum;

import java.lang.annotation.*;

/**
* 订单类型注解
* 使用方式:
* 1:普通订单 @OrderTypeHandlerAnno("1")
* 2:团购订单 @OrderTypeHandlerAnno("2")
* 3:促销订单 @OrderTypeHandlerAnno("3")
*/
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
public @interface OrderTypeHandlerAnno {

OrderTypeEnum value();

}

GroupOrderHandler

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
package com.oy.test.handler.biz;

import com.oy.test.bean.OrderDTO;
import com.oy.test.common.OrderTypeEnum;
import com.oy.test.handler.AOrderTypeHandler;
import com.oy.test.handler.OrderTypeHandlerAnno;
import org.springframework.stereotype.Component;

/**
* 团队订单处理
*/
@Component
@OrderTypeHandlerAnno(OrderTypeEnum.Group)
public class GroupOrderHandler extends AOrderTypeHandler {

@Override
public String handler(OrderDTO dto) {
return "处理团队订单";
}

}

NormalOrderHandler

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
package com.oy.test.handler.biz;

import com.oy.test.bean.OrderDTO;
import com.oy.test.common.OrderTypeEnum;
import com.oy.test.handler.AOrderTypeHandler;
import com.oy.test.handler.OrderTypeHandlerAnno;
import org.springframework.stereotype.Component;

/**
* 普通订单处理
*/
@Component
@OrderTypeHandlerAnno(OrderTypeEnum.Normal)
public class NormalOrderHandler extends AOrderTypeHandler {

@Override
public String handler(OrderDTO dto) {
return "处理普通订单";
}
}

PromotionOrderHandler

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
package com.oy.test.handler.biz;

import com.oy.test.bean.OrderDTO;
import com.oy.test.common.OrderTypeEnum;
import com.oy.test.handler.AOrderTypeHandler;
import com.oy.test.handler.OrderTypeHandlerAnno;
import org.springframework.stereotype.Component;

/**
* 促销订单处理
*/
@Component
@OrderTypeHandlerAnno(OrderTypeEnum.Promotion)
public class PromotionOrderHandler extends AOrderTypeHandler {

@Override
public String handler(OrderDTO dto) {
return "处理促销订单";
}

}

OrderDTO

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
package com.oy.test.bean;

import java.math.BigDecimal;

public class OrderDTO {
private String code;
private BigDecimal price;

/*
* 订单类型:
* 1:普通订单
* 2:团购订单
* 3:促销订单
*/
private String type;

public String getCode() {
return code;
}

public void setCode(String code) {
this.code = code;
}

public BigDecimal getPrice() {
return price;
}

public void setPrice(BigDecimal price) {
this.price = price;
}

public String getType() {
return type;
}

public void setType(String type) {
this.type = type;
}
}

OrderTypeEnum

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
package com.oy.test.common;

/**
* 订单类型枚举
*/
public enum OrderTypeEnum {
Normal("1", "普通"),
Group("2", "团队"),
Promotion("3", "促销");

private String code; //代码
private String name; //名称,描述

OrderTypeEnum(String code, String name) {
this.code = code;
this.name = name;
}

public String getCode() {
return code;
}

public void setCode(String code) {
this.code = code;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

/**
* 根据code属性获取name属性
*
* @param code
* @return
*/
public static String getNameByCode(String code) {
for (OrderTypeEnum temp : OrderTypeEnum.values()) {
if (temp.getCode().equals(code)) {
return temp.getName();
}
}
return null;
}

}

service

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
/**
* 订单处理
*/
public interface IOrderService {

/**
* 根据订单的不同类型做出不同的处理
*
* @param dto 订单实体
* @return 为了简单,返回字符串
*/
String orderHandler(OrderDTO dto);
}

/**
* 原始逻辑代码
**/
@Service
public class OrderServiceImpl implements IOrderService {

@Override
public String orderHandler(OrderDTO dto) {
if ("1".equals(dto.getType())) {
//普通订单处理
} else if ("2".equals(dto.getType())) {
//团购订单处理
} else if ("3".equals(dto.getType())) {
//促销订单处理
}
return null;
}

}

/**
* 使用设计模式简化
**/
@Service
public class OrderServiceImpl2 implements IOrderService {
//使用策略模式实现
@Autowired
private HandlerContext handlerContext;

@Override
public String orderHandler(OrderDTO dto) {
/*
* 1:使用if..else实现
* 2:使用策略模式实现
*/
AOrderTypeHandler instance = handlerContext.getInstance(dto.getType());
return instance.handler(dto);
}

}

二、策略模式+工厂方法

我们把每个条件逻辑代码块,抽象成一个公共的接口,我们根据每个逻辑条件,定义相对应的策略实现类

image-20211122110150669

interface 接口

1
2
3
public interface NameService {
String getName();
}

service

1
2
3
4
5
6
7
8
public class LisiName implements NameService {
@Override
public String getName() {
// 李四业务逻辑...
System.out.println("我是李四");
return "我是李四";
}
}
1
2
3
4
5
6
7
8
public class WangwuName implements NameService {
@Override
public String getName() {
// 王五业务逻辑...
System.out.println("我是王五");
return "我是王五";
}
}
1
2
3
4
5
6
7
8
public class ZhansanName implements NameService {
@Override
public String getName() {
// 张三业务逻辑...
System.out.println("我是张三");
return "我是张三";
}
}

factory

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public class NameServiceFactory {

private static final Map<String, NameService> map = new HashMap<>();

static {
map.put("张三", new ZhansanName());
map.put("李四", new LisiName());
map.put("王五", new WangwuName());
}

public static NameService getNameService(String name){
return map.get(name);
}

}

测试

1
2
3
4
public static void main(String[] args) {
NameService nameService = NameServiceFactory.getNameService("张三");
nameService.getName();
}