设计模式

Mars 2020年05月12日 38次浏览

设计模式概念以及demo

国外网站详解设计模式

设计模式实际应用

责任链模式

  • 前言
    责任链模式使用的地方比较多,但是大部分都不是很纯的责任链
    • 一个纯的责任链模式要求一个具体的处理者对象只能在两个行为中选择一个
      一是承担责任,而是把责任推给下家。不允许出现某一个具体处理者对象在承担了一部分责任后又 把责任向下传的情况。在一个纯的责任链模式里面,一个请求必须被某一个处理者对象所接收;
    • 在一个不纯的责任链模式里面,一个请求可以最终不被任何接收端对象所接收。
    • 纯的责任链模式的实际例子很难找到,一般看到的例子均是不纯的责任链模式的实现。有些人认为不纯的责任链根本不是责任链模式,这也许是有道理的。但是在实际的系统里,纯的责任链很难找到。如果坚持责任链不纯便不是责任链模式,那么责任链模式便不会有太大意义了。

tomcat里面有比较常见的责任链模式,比如Filter的设计,但它不是一个纯的责任链。

  • 实际开发使用场景-1
    • 场景描述
      我们的部分同步的rpc请求通过feign来发送的,但是早期代码并未使用注解方式,而是手动创建feign客户端来发送的,因此为了方便,最初他们在设计时是引入了自定义注解@CatfishClient,为该注解标记的实例生成feign的代理对象,并注入容器。为了便于扩展,在使用feign的代理对象发送rpc请求之前会执行一个chain filter,此处便是使用责任链模式设计
    • 创建责任链
      我们定义了一个Filter接口,接口包含抽象方法invoke,并在spring容器启动之后获取到所有Filter类型的bean,排好序之后构建为一个filter链
    • 调用
      在每次通过feign的代理对象发送具体的rpc请求之前,我们会依次调用filter链上的所有filter的invoke方法
    • 扩展
      只需要实现Filter接口,并交给spring容器管理即可
    • 我们具体的Filter实现
      比如我们有个统计任务信息的Filter实现,若同类型的任务占用大量的线程则会告警,更严重的会直接拒绝此次rpc请求

策略模式

  • 前言
    个人认为策略模式最大的好处是扩展性,以及没有了大量的if else
  • 实际开发使用场景-1
    • 场景描述
      这是mock工具,模拟生成我们地铁系统所有的文件来源,文件可能有几十个(比如R01、R02、R07等文件),每一种都是一个单独文件夹,文件夹里面由多个具体的文件构成,比如有.mv、.idx(这是我们自定义的一种索引文件)、.point、.log等等具体的文件。前期的文件只有十个不到,后期会逐步增加。因此我们采取策略模式生成这些模拟文件(这种结构是铁路局那边回传到我们这边的数据,所有的都是R01、R02这种方式的文件夹,每个文件夹里面包含了很多具体文件,我们所要做的就是模拟这些数据)。
    • 准备
      首先定义每一种具体文件的处理类,且这些处理类都实现了公共接口Handler
    	# 实现类全限定名
    	mv=*.*.*.MvFileHandler
    	idx=*.*.*.IDXFileHandler
    	log=*.*.*.LogFileHandler
    	...
    

    其次再定义一个文件夹和具体的文件映射

    	R01=mv,idx
    	R07=log,idx,point
    	...
    
    • 策略模式的实现
      • 在mock启动阶段,扫描到所有Handler的实现并保存到指定map,key为当前handler实现类的全限定名
      • 当有文件请求过来,先判断属于哪一种类型的文件(如R01,R02),之后根据文件类型找到需要生成的具体文件有哪些(如.idx、.log),之后根据具体文件名找到对应得handler,再异步分发给每个具体实现handler生成具体的文件
    • 扩展性
      • 当有新的文件夹类型增加(如R09类型的文件里面包含idx文件和log文件),但没有具体文件增加,此时只需增加配置即可,无须改动代码
      	R09=log,idx
      
      • 当有新的文件夹类型增加(如R11类型的文件里面包含idx文件和log文件),我们只需增加新的handler实现类SyncFileHandler和增加配置即可,对原来代码也没有任何污染
      	sync=*.*.*.SyncFileHandler
      

      	R11=log,sync
      
  • 实际开发使用场景-2
    • 场景描述
      这是一个对接系统,负责和外部的很多合作公司交互。每次请求进入我们系统,我们会根据不同的命令分发到不同的公司、该公司不同的接口
    • 实现
      • 同理,也是准备了很多handler,这些handler根据company_id+command作为key,自身的handler实例作为value存入内存中
      • 之后当请求打到我们对接系统,就会进入我们的Dispatcher进行分发(根据company_id和command找到对应得handler)进行不同的处理
    • 扩展
      当有新的公司接入,我们只需要新增handler即可
  • 实际开发使用场景-3
    • 如Spring MVC中的ServletDispatcher即是策略模式的实现

单例模式

观察者(监听)模式