设计模式-策略模式【实战】
通常面试题:项目中你认为设计好的地方有哪些,项目中的设计模式是怎么用的?为什么要用设计模式…
通常这样的问题,就开始自我吹嘘,解耦,高内聚低耦合啥的… 面试官一脸黑
废话少说上设计模式,讲讲我的理解。
策略模式:
策略模式允许你定义一系列算法,将每个算法封装起来,并使它们可以互相替换。在这种情况下,每个查询类型可以被视为一个不同的策略,它们可以根据查询类型的不同而执行不同的查询操作。
场景:
举例说明:
公司项目不方便举例,这边用查询图书举例。
1,有三个模块【分别是:小学、初中、高中】,分别要查询分别对应书,以及课本详情
2,操作对象都是书,可能就是dto的参数不同,数据类型是相同的
3,通常设计dto用于接收参数,加一个字段 queryType 用于区分不同的查询类型
写法一:【未用设计模式之前】
controller
@Autowired
private BookService bookService;
@PostMapping("/queryBookListByDto")
public List<BookVo> queryBookListByDto(@RequestBody BookDto dto){
return bookService.queryBookListByDto(dto);
}
service
/**
* @author psd
*/
public interface BookService {
/**
* 根据dto查询书的集合
*
* @param dto
* dto对象
* @return 书的集合
*/
List<BookVo> queryBookListByDto(BookDto dto);
}
serviceImpl
@Autowired
private Map<Integer, QueryStrategy> queryStrategyMap;
@Override
public List<BookVo> queryBookListByDto(BookDto dto) {
List<BookVo> bookVoList = new ArrayList<>();
switch (dto.getQueryType()){
case 1:
// 执行查询逻辑
bookVoList = queryStrategyMap.queryBookListByDto(BookDto dto);
return ;
case 2:
// 执行查询逻辑
bookVoList = queryStrategyMap.queryBookListByDto(BookDto dto);
return ;
case 3:
// 执行查询逻辑
bookVoList = queryStrategyMap.queryBookListByDto(BookDto dto);
return ;
default:
}
return bookVoList ;
}
dto
/**
* @author psd
*/
@Data
public class BookDto {
/**
* 作者名字
*/
private String authName;
/**
* 查询的类型 1:小学 2:中学 3:高中 4:大学
*/
private Integer queryType;
}
写法二:【策略模式书写】
步骤:
1,定义一个接口用来表示不同的查询策略
2,每种查询都实现这个接口,重写里面的方法,实现不同的查询策略
3,将所有的策略类注入到一个Map中,以便根据查询类型来选择相应的策略
4,使用的时候获取指定的策略,执行查询方法
1,定义一个接口用来表示不同的查询策略
/**
* @author psd
*/
public interface QueryStrategy {
/**
* 查询书籍
*
* @param dto
* 查询条件
* @return 书的集合
*/
List<BookEntity> executeQuery(BookDto dto);
}
2、每种查询都实现这个接口,重写里面的方法,实现不同的查询策略
小学
/**
* @author psd 小学
*/
@Service
public class PrimarySchool implements QueryStrategy {
@Autowired
private BookMapper bookMapper;
@Override
public List<BookEntity> executeQuery(BookDto dto) {
// TODO:小学的看的书
return null;
}
}
初中
/**
* @author psd 初中
*/
@Service
public class JuniorHighSchool implements QueryStrategy {
@Autowired
private BookMapper bookMapper;
@Override
public List<BookEntity> executeQuery(BookDto dto) {
return null;
}
}
高中
/**
* @author psd 高中
*/
@Service
public class SeniorHighSchool implements QueryStrategy {
@Autowired
private BookMapper bookMapper;
@Override
public List<BookEntity> executeQuery(BookDto dto) {
return null;
}
}
3、将所有的策略类注入到一个Map中,以便根据查询类型来选择相应的策略
/**
* @author psd 执行查询策略配置
*/
@Configuration
public class ExecuteQueryStrategyConfig {
@Autowired
private JuniorHighSchool juniorHighSchool;
@Autowired
private SeniorHighSchool seniorHighSchool;
@Autowired
private PrimarySchool primarySchool;
@Bean
public Map<Integer, QueryStrategy> queryStrategyMap() {
return Map.of(
1, juniorHighSchool,
2, seniorHighSchool,
3, primarySchool
);
}
}
4、使用的时候获取指定的策略,执行查询方法
/**
* @author psd
*/
@Service
public class BookServiceImpl implements BookService {
@Autowired
private Map<Integer, QueryStrategy> queryStrategyMap;
@Override
public List<BookVo> queryBookListByDto(BookDto dto) {
// 获取指定的查询策略
QueryStrategy queryStrategy = queryStrategyMap.get(dto.getQueryType());
// 执行查询方法
List<BookEntity> entities = queryStrategy.executeQuery(dto);
// 数据类型转换
return entities.stream().map(x -> {
BookVo vo = new BookVo();
BeanUtils.copyProperties(x, vo);
return vo;
}).collect(Collectors.toList());
}
}
谈谈我的理解:
1,为啥要用到设计模式,主要是解耦,用我自己话,让代码看起来简洁,高内聚低耦合,少用if else 或者switch…
2,后面如果再有类似的查询,直接编写实现类去实现查询策略接口,编写自己内部的查询逻辑即可,减少代码的依赖性
3,编写高质量的代码
注意事项:
1,使用策略模式时候,在传参时候要做参数校验比如queryTyep查询类型,必须是哪几个值
2,在实现策略的实现类里面,需要使用mapper 或者service的时候,要考虑到是否放到spring容器里面,避免null的问题。
喜欢我的文章的话,点个阅读或者点个点赞,是我编写博客的动力,持续更新中 ing…