设计模式的优雅不必多说,最近也是好好研究了一下,利用设计模式给我的项目做了好多优化,优化过后代码果然变得很漂亮。接下来盘点一下我都做了哪些优化。

责任链模式+迭代器模式优化实现内推帖子审核功能

内推信息的发布内容是需要审核的,我在这里就大体可以分成三部分

  1. 基础审核(包括字数、不能包括可能导致页面混乱的代码出现等等)
  2. 敏感词审核(调用阿里云的敏感词检测API,也可以用其他的)
  3. 检测图片是否违规(抽取图片链接,检测是否合法)

初步想法:

  1. 创建抽象处理者
public interface ReviewHandler{
Result review(Article article);
}
  1. 创建三个审核步骤的实现类(具体处理者),它们都继承抽象处理者,分别是 BaseReviewHandler、

SensitiveWordReviewHandler、ImageReviewHandler。三个类上均需要加上@Component,交由Spring进行管理,其中BaseReviewHandler上加了@Primary,表示当前这个类会被第一个调用。(因为三个类要依次审核嘛);

@Primary
@Component
class BaseReviewHandler implements ReviewHandler{

@Autowired
private SensitiveWordReviewHandler sensitiveWordReviewHandler;

@override
public Result review(Article article){
//进行基础审核,检查字数是否达标
int wordCount article.getContent().split(regex:"\\s+").length
if (wordCount <100){
//没有问题了会进入到下一个审核对象,继续审查
return sensitiveWordReviewHandler.review(article);
}else{
return new Result(false,"字数违规!");
}
}
}

SensitiveWordReviewHandler、ImageReviewHandler同上,只不过ImageReviewHandler审核完成后会直接返回,而不是给下一条。

对于审核帖子的Service只需要注入ReviewHandler即可,以为第一个已经加上了@Primary,会自动第一个。

加迭代器模式优化:

利用上面的单独的责任链模式实现是可以的,但是我立马发现一个问题,那就是如果我这个帖子没有图片我还得走这个ImageReviewHandler,我只能按照确定好的顺序进行审核吗,我想增加新的审核节点怎么办?灵魂三连问。这也太不灵活了。当我学到迭代器模式后,一个优化方案油然而生。

具体实现:

首先就是要在内推帖子实体类中加一个属性(文章审核策略 reViews),这个策略要在前端进行选择(这里必须在前端给出选项,用户可以单选,多选,切换顺序)。

比如以下三个选项SENSITIVE、BASE、IMAGE。然后要在原来@Component中加上名字变成@Component(“BASE”)等。

最后就是使用迭代器了。

buildHandlers读出来前端穿过来的审核策略然后按照名称进行注入进来(可以用hutool包里的StringUtil.getBean(beanName)方法)。然后通过迭代器Iterator判断是否有下一个,如果有就执行,每一个执行后都会返回result,如果返回错误,就直接返回错误就行了,全部审核通过就可以返回审核通过。这么一来,就提高了审核流程的灵活性。

策略模式+工厂模式优化多种登录方式

受限于个人开发。这个优化虽然我没有具体实现,但是具体流程还是很清晰的,某天企业需要,我觉得是可以把它实现的。

在登陆入口处,登录方式可以有很多种用户名密码登录、短信验证码登录、微信登录、QQ登录等等

所以在实现的时候,如果按照原方法,从前端传过来的LoginReq中type参数,需要使用很多if else进行判断,并且想添加新的登录方式的时候还要重新修改原代码。这个时候,策略模式就派上大用场了,他是专门应对这种多个判断共存的情景的,他经常和工厂模式联合使用。

具体架构

暂时无法在飞书文档外展示此内容

我们可以将这些登录写到yml配置文件中。工厂负责

  1. 读取配置准备对象
  2. 根据参数提供配置
login:
types:
account: accountGranter //key要对应前端传过来的名字,value要对应策略方法
sms:smsGranter
wechat:weChatGranter

首先写一个抽象策略接口,里面有一个login方法,然后将每一种登录方式写成具体策略类,它们都实现抽象策略接口并重写每一种登录方法。

工厂中创建一个map集合,从配置文件中读取策略类存储到map中,map的key放account、sms、wechat。value放具体的策略类。可以利用实现ApplicationContextAware接口,重写setApplicationContext,拿到applicationContext,通过它的getBean(y)拿到bean对象,还要提供一个方法对外提供获取具体策略getGranter

public UserGranter getGranter(String grantType){
UserGranter tokenGranter = granterPool.get(grantType);
return tokenGranter;
}

这样service中只需要注入工厂,然后通过factory.getFranter(LoginReq.getType())即可使用对应的登录方式,这样依赖就可以实现在添加新登陆方法时既不用该service,也不用修改工厂了。