设计模式-模板方法模式

参考文档:

  1. 模板方法模式
  2. 设计模式之美-王争

Define the skeleton of an algorithm in an operation, deferring some steps to subclasses. Template Method lets subclasses redefine certain steps of an algorithm without changing the algorithm’s structure20

模板方法模式在一个方法中定义一个算法骨架,并将某些步骤推迟到子类中实现。模板方法模式可以让子类在不改变算法整体结构的情况下,重新定义算法中的某些步骤。

应用场景

最近在做第三方厂商的SDK对接,每个厂商都有自己的鉴权体系,基本上都是通过appKey、appSecret去换取Token。由于获取Token的方法可能会被限频,那我们就需要考虑把Token缓存起来;其次,一个Token有效期大约为2个小时,那我们还需要考虑达到某个时间阈值,如过期时间小于30分钟后,我们需要刷新Token
具体流程图如下:

image.png

问题来了,今天我要对接钉钉,我写了一个获取Token的方法并引入了缓存、考虑了Token的刷新,明天我要去对接飞书、北森的开放接口,我发现,这代码简直80%都一样啊!
这里模板方法看起来好像是一个不错的设计模式,我们好像可以引入。

  • 模板模式作用一:复用

通过泛型+模板方法流程中不变的东西实现,将GenerateRedisKey、GetToken,让具体的子类实现。

  • 模板模式作用二:扩展

现在我需要对接飞书,实现Token的方法,我只需要继承实现TokenTemplate中的GenerateRedisKey、GetToken的方法就可以实现Token的缓存、刷新功能,在不改变原有代码的基础上,添加了新的特性。

BearerToken Token的基类模型

image.png
首先我们创建一个BearerToken的abstract基类模型,由于每个厂商接口返回的模型、业务编码可能都不一样的,子类的结果模型需要实现以下两个方法。

        /// <summary>
        /// 判断Token是否获取成功
        /// </summary>
        /// <returns></returns>
        public abstract bool IsSuccess();
        
        /// <summary>
        /// 获取过期时间
        /// 单位:s
        /// </summary>
        /// <returns></returns>
        public abstract long GetExpireTime();
复制代码

抽象父类TokenTemplate

image.png

DingTalkToken 实现

image.png

FeiShuToken 实现

image.png

总结

模板方法对于具有流程性的业务逻辑易于扩展和实现,但是如果遇到某个客户端存在独立的特性,比如钉钉和飞书的接口返回值都提供了一个code的业务编码,但是北森接口需要你根据HttpStatusCode(Http状态码)来判断,那我们就需要在模板中添加一个状态码的判断,但实际上钉钉和飞书,并没有Http状态码,这就可能违反里氏替换原则。

软件开发过程成中往往是没有对错的,需要我们多方面的考量和权衡。

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享