java设计模式之责任链模式、状态模式、策略模式

若您对我的分享感兴趣可以访问:java设计模式专栏

在常用的23中设计模式中,有三种模式容易混淆,这三种模式分别是:责任链模式、状态模式以及策略模式

因此接下来我们把这三种模式放在一起讨论

1、责任链模式(okHttp)
职责链的本质是:不同的类对同一个问题的反应
    责任链模式下处理者所处的位置决定了其功能,在这里,最后一个 Interceptor 一定是负责和服务器实际通讯的,重定向、缓存等一定是在实际通讯之前的
责任链实现的关键有:
(1)需要责任链上一系列的处理类实现统一的接口
(2)需要有管理器来指定所有处理类的拦截处理顺序
(3)每一个责任链上的处理对类都明确自己可以处理的命令,也知道如何将自己不能处理的命令传递给该链中的下一个处理对象
(4)该模式还描述了往该处理链的末尾添加新的处理对象的方法

例如:
OkHttp的网络请求拦截处理链就很好的实现了责任链的模式
责任链模式在 Interceptor 链条中得到了很好的实践,所有的拦截器都实现了统一的接口,请求在多个肩负不同功能的拦截器组成的链条中进行传递,每个拦截器都有机会处理请求。具体哪个拦截器处理请求需要由运行时刻自动确定
对于把 Request 变成 Response 这件事来说,每个 Interceptor 都可能完成这件事,所以我们循着链条让每个 Interceptor 自行决定能否完成任务以及怎么完成任务(自力更生或者交给下一个 Interceptor)这样一来,完成网络请求这件事就彻底从 RealCall 类中剥离了出来,简化了各自的责任和逻辑

责任链模式在安卓系统中也有比较典型的实践,例如 view 系统对点击事件(TouchEvent)的处理

2、状态模式

状态模式目的or意图:

    控制一个对象内部的状态转换的条件表达式过于复杂时的情况,且客户端调用之前不需要了解具体状态。它把状态的判断逻辑转到表现不同状态的一系列类当中,可以把复杂的判断逻辑简化

其本质是:一个类对不同状态的多种不同响应

关键:

状态模式是让各个状态对象自己知道其下一个处理的对象是谁!即在状态子类编译时在代码上就设定好了!

https://www.cnblogs.com/kubixuesheng/p/5180509.html

状态模式和责任链模式的比较:

    区别在于状态模式需要各个状态类(类比责任链上的各个职责类),明确知道自己的下一个需要转移的状态是什么,而责任链模式里的责任类不需要知道自己的下一个需要转移的职责是哪个,等价于——发出完成某任务请求的客户端并不知道链上的哪一个对象最终处理这个请求,这个组装过程需要交给环境类去完成

重点:(最重要的区别)

状态模式需要各个状态类,明确知道自己的下一个需要转移的状态是什么,所有的状态类一起组装了请求的处理逻辑

责任链模式上的责任类,不需要不需要知道自己的下一个需要转移的职责是哪个这个组装过程需要交给环境类去完成

    比如,政府部分的某项工作,县政府先完成自己能处理的部分,不能处理的部分交给省政府,省政府再完成自己职责范围内的部分,不能处理的部分交给中央政府,中央政府最后完成该项工作。但是以上的责任的转移,或者说在责任链上的移动,各个责任类不知道具体顺序和下一个责任,链条的组装过程是环境类(或客户端完成的)

一般来说责任链重要的是环境类,通过环境类其指定各个责任类的执行顺序,非常灵活

每个责任类只需要完成自己的工作其他的不需要考虑

但是还有一种写法是责任链也是可以指定下一个责任类,那么这个时候区分两种模式的就要使用终极大杀器了

需要注意的是:状态模式出现的根本原因是需要对自身的状态进行改变

而责任链模式是对一个事件的处理

极大程度简化了这些操作


3、策略模式(retrofit)

什么叫做策略,我们可以把策略理解成备选,那么策略模式就是用来解决当出现一个问题的时候,我们会有很多种备选方案,如何完美的利用这些备选方案,而又符合程序的设计美学,这就是策略模式的存在的必要性
可能你会认为那不就是一些if else 或者switch case 就可以解决的问题吗,不错,if else 确实可以非常有效的解决问题,但是如果出现需要扩展的情况呢?如果你的if else 部分的代码是不对外开放的,无法及时修改怎么办呢?
上面这些问题其本质就是使用if else 是不符合OCP原则的,也就是不能同时满足对扩展开放,对修改关闭的原则,而使用策略模式就可以完美解决这个问题
例如:一个应用可能需要多种主题风格
我们就可以使用策略模式来实现主题的切换
步骤:
(1)创建一个主题接口
(2)创建一个维护主题接口的上下文,此上下文对象包含一个主题接口的引用,和设置主题的方法
(3)然后我们就可以实现主题接口的具体策略,例如主题方案1,方案2,方案....
(4)调用的时候我们只需要将对应的主题方案传递给上下文,然后调用上下文对象的设置主题的方法就可以了,最重要的是if else不见了
(5)那么如果我们想要再添加一个主题方案怎么办?很简单添加一个主题接口的实现类然后调用就可以
(6)这样我们可以把主题接口,主题接口的上下文,默认的主题方案等这些东西作为上层封装起来,关闭下层调用者的修改权限,但是保留了其扩展的权限


当然策略模式可以和其他模式结合起来使用例如:
当我们的应用里面的主题过于复杂的时候我们就可以使用工厂模式去生产主题,将所有的主题的生产维护在一个主题工厂里面


那么两者结合起来就是:
(1)用户调用主题工厂生产一个主题
(2)用户调用主题上下文对象切换指定主题
非常简洁明了
可是有人会问,在客户端调用的时候,还是会new一个具体的对象啊,这样就会产生依赖,是的,这就是注入依赖要解决的问题咯,本文不做深入的探讨


在举例:
假如有一个电商网站系统,针对男性女性用户要各自跳转到不同的商品类目,并且所有的广告位展示不同的广告。在传统的代码中,都是在系统中加入各种if else的判断,硬编码的方式。如果有一天增加了一种用户,就需要改写代码。使用策略模式,如果新增加一种用户类型,只需要增加一种策略就可以

状态模式和策略模式的比较
  实现目的不一样!
  首先知道,策略模式是一个接口的应用案例,一个很重要的设计模式,简单易用,策略模式一般用于单个算法的替换,客户端事先必须知道所有的可替换策略,由客户端去指定环境类需要哪个策略,注意通常都只有一个最恰当的策略(算法)被选择。其他策略是同级的,可互相动态的在运行中替换原有策略,(注意关键是策略模式需要客户端了解策略)

    而状态模式的每个状态子类中需要包含环境类(Context)中的所有方法的具体实现——条件语句,通过把行为和行为对应的逻辑包装到状态类里,在环境类里消除大量的逻辑判断,而不同状态的切换由继承(实现)State的状态子类去实现,当发现修改的当前对象的状态不是自己这个状态所对应的参数,则各个状态子类自己给Context类切换状态(有职责链模式思想)

    且客户端不直接和状态类交互,客户端不需要了解状态!(和策略不一样),策略模式是直接依赖注入到Context类的参数进行选择策略,不存在切换状态的操作,客户端需要了解策略!

联系:

    状态模式和策略模式都是为具有多种可能情形设计的模式,把不同的处理情形抽象为一个相同的接口(抽象类),符合对开闭原则,且策略模式更具有一般性,在实践中,可以用策略模式来封装几乎任何类型的规则,只要在分析过程中听到需要在不同实践应用不同的业务规则,就可以考虑使用策略模式处理,在这点上策略模式是包含状态模式的功能的。


你可能感兴趣的:(JAVA,java设计模式)