原文链接:https://blog.csdn.net/hncu1306602liuqiang
看到crossover Jie的文章《利用策略模式优化过多if else 代码》后受到启发,可以利用策略模式简化过多的if else代码。

需求

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

项目结构

订单实体

/**

 * 订单实体

 */

publicclassOrderDTO {
private
 String code;

private
 BigDecimal price;


/*

     * 订单类型:

     * 1:普通订单

     * 2:团购订单

     * 3:促销订单

     */

private
 String type;

//getter,setter自己实现
}

service接口

/**

 * 订单处理

 */

publicinterfaceIOrderService
{


/**

     * 根据订单的不同类型做出不同的处理

     *

     * 
@param
 dto 订单实体

     * 
@return
 为了简单,返回字符串

     */

String orderHandler(OrderDTO dto)
;


}

//实现类1
@Component
publicclassOrderServiceImplimplementsIOrderService
{


@Override
public String orderHandler(OrderDTO dto)
{

if
 (
"1"
.equals(dto.getType())) {

//普通订单处理
        } 
elseif
 (
"2"
.equals(dto.getType())) {

//团购订单处理
        } 
elseif
 (
"3"
.equals(dto.getType())) {

//促销订单处理
        }

//未来订单类型增加
    }


}

//实现类二
@Component
publicclassOrderServiceImplimplementsIOrderService
{

//使用策略模式实现
@Autowired
private
 HandlerContext handlerContext;


@Override
public String orderHandler(OrderDTO dto)
{

/*

         * 1:使用if..else实现

         * 2:使用策略模式实现

         */

        AOrderTypeHandler instance = handlerContext.getInstance(dto.getType());

return
 instance.handler(dto);

    }


}

利用策略模式只需要2行代码就可以搞定(也可以用工厂)
HandlerContext和HandlerProccessor

/**

 * 订单策略模式环境

 * 这个类的注入由HandlerProccessor实现

 */

publicclassHandlerContext
 {

private
 Map<String, AOrderTypeHandler> handlerMap;


/**

     * 构造传参不能直接使用注解扫入

     */

publicHandlerContext(Map<String, AOrderTypeHandler> handlerMap
{

this
.handlerMap = handlerMap;

    }


/**

     * 获得实例

     *

     * @param type

     * @return

     */

public AOrderTypeHandler getInstance(String type
{

if
 (type == 
null
) {

thrownew
 IllegalArgumentException(
"type参数不能为空"
);

        }

        AOrderTypeHandler clazz = handlerMap.
get
(type);

if
 (clazz == 
null
) {

thrownew
 IllegalArgumentException(
"该类型没有在枚举OrderTypeHandlerAnno中定义,请定义:"
 + type);

        }

return
 clazz;

    }


}

/**

 * 策略模式,处理type与实现类的映射关系

 */

@Component
publicclassHandlerProccessorimplementsBeanFactoryPostProcessor
{


/**

     * 扫描
@OrderTypeHandlerAnno
注解,初始化HandlerContext,将其注册到spring容器

     *

     * 
@param
 beanFactory bean工厂

     * 
@throws
 BeansException

     */

@Override
publicvoidpostProcessBeanFactory(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> 
getBeansWithAnnotation(ConfigurableListableBeanFactory beanFactory, Class<T> manager, Class<? extends OrderTypeHandlerAnno> annotation, String code)throws BeansException 
{

if
 (ObjectUtils.isEmpty(code)) {

thrownew
 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)) {

thrownew
 RuntimeException(
"该注解没有写入值 :"
 + code);

            }

//注解值是否与code相等
if
 (code.equals(orderTypeHandlerAnno.value().getCode())) {

return
 t;

            }

        }

thrownew
 RuntimeException(
"通过code没有找到该注解对应的实体类 :"
 + code);

    }


}

父抽象类+注解+枚举

/**

 * 订单类型处理定义

 * 使用抽象类,那么子类就只有一个继承了

 */

publicabstractclassAOrderTypeHandler
{


/**

     * 一个订单类型做一件事

     *

     * 
@param
 dto 订单实体

     * 
@return
 为了简单,返回字符串

     */

abstractpublic String handler(OrderDTO dto)
;


}


/**

 * 订单类型注解

 * 使用方式:

 * 1:普通订单 
@OrderTypeHandlerAnno
("1")

 * 2:团购订单 
@OrderTypeHandlerAnno
("2")

 * 3:促销订单 
@OrderTypeHandlerAnno
("3")

 */

@Target
({ElementType.TYPE})

@Retention
(RetentionPolicy.RUNTIME)

@Documented
@Inherited
public@interface
 OrderTypeHandlerAnno {


OrderTypeEnum value()
;


}


/**

 * 订单类型枚举

 */

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

    }


publicvoidsetCode(String code)
{

this
.code = code;

    }


public String getName()
{

return
 name;

    }


publicvoidsetName(String name)
{

this
.name = name;

    }


/**

     * 根据code属性获取name属性

     *

     * 
@param
 code

     * 
@return
     */

publicstatic String getNameByCode(String code)
{

for
 (OrderTypeEnum temp : OrderTypeEnum.values()) {

if
 (temp.getCode().equals(code)) {

return
 temp.getName();

            }

        }

returnnull
;

    }


}

业务人员实现类
//业务代码
/**

 * 普通订单处理

 */

@Component
@OrderTypeHandlerAnno
(OrderTypeEnum.Normal)

publicclassNormalOrderHandlerextendsAOrderTypeHandler
{


@Override
public String handler(OrderDTO dto)
{

return"处理普通订单"
;

    }


}


/**

 * 团队订单处理

 */

@Component
@OrderTypeHandlerAnno
(OrderTypeEnum.Group)

publicclassGroupOrderHandlerextendsAOrderTypeHandler
{


@Override
public String handler(OrderDTO dto)
{

return"处理团队订单"
;

    }


}


/**

 * 促销订单处理

 */

@Component
@OrderTypeHandlerAnno
(OrderTypeEnum.Promotion)

publicclassPromotionOrderHandlerextendsAOrderTypeHandler
{


@Override
public String handler(OrderDTO dto)
{

return"处理促销订单"
;

    }


}

测试结果(使用chrome浏览器测试结果)
如果类型不存在
controller


/**

 * 策略模式

 */

@RestController

public 
classStrategyController
{

    @Resource(name = 
"orderServiceImpl"
)

    private IOrderService orderService;


    @GetMapping(
"/api/order"
)

    @ResponseBody

    public 
String
 orderSave(OrderDTO dto) {

String
 str = orderService.orderHandler(dto);

return"{\"status\":1,\"msg\":\"保存成功\",\"data\":\""
 + str + 
"\"}"
;

    }


}

pom.xml文档


<?xml version=
"1.0"
 encoding=
"UTF-8"
?>

<
projectxmlns
=
"http://maven.apache.org/POM/4.0.0"xmlns:xsi
=
"http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation
=
"http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"
>

<modelVersion>
4.0.0
</modelVersion>
<parent>
<groupId>
org.springframework.boot
</groupId>
<artifactId>
spring-boot-starter-parent
</artifactId>
<version>
2.2.1.RELEASE
</version>
<relativePath/><!-- lookup parent from repository -->
</parent>
<groupId>
com.kayak
</groupId>
<artifactId>
study-design
</artifactId>
<version>
0.0.1-SNAPSHOT
</version>
<name>
study-design
</name>
<description>
Demo project for Spring Boot
</description>

<properties>
<java.version>
1.8
</java.version>
</properties>

<dependencies>
<dependency>
<groupId>
org.springframework.boot
</groupId>
<artifactId>
spring-boot-starter-web
</artifactId>
</dependency>

<dependency>
<groupId>
org.springframework.boot
</groupId>
<artifactId>
spring-boot-starter-test
</artifactId>
<scope>
test
</scope>
<exclusions>
<exclusion>
<groupId>
org.junit.vintage
</groupId>
<artifactId>
junit-vintage-engine
</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>

<build>
<plugins>
<plugin>
<groupId>
org.springframework.boot
</groupId>
<artifactId>
spring-boot-maven-plugin
</artifactId>
</plugin>
</plugins>
</build>

</project>

总结:

利用策略模式可以简化复杂的if else代码,方便维护,而利用自定义注解和自注册的方式,可以方便应对需求的变更。
主要是方便了业务人员编写代码。
这个就是个人笔记,不喜勿喷。
  • —————END—————
PS:如果觉得我的分享不错,欢迎大家随手点赞、在看。
 关注公众号:Java后端编程,回复下面关键字 
要Java学习完整路线,回复  路线 
缺Java入门视频,回复 视频 
要Java面试经验,回复  面试 
缺Java项目,回复: 项目 
进Java粉丝群: 加群 
PS:如果觉得我的分享不错,欢迎大家随手点赞、在看。
(完)
加我"微信获取一份 最新Java面试题资料
请备注:666不然不通过~
最近好文
最近面试BAT,整理一份面试资料Java面试BAT通关手册,覆盖了Java核心技术、JVM、Java并发、SSM、微服务、数据库、数据结构等等。
获取方式:关注公众号并回复 java 领取,更多内容陆续奉上。
明天见(。・ω・。)ノ♡
继续阅读
阅读原文