行为型模式(10)——策略模式

定义

该模式定义了一系列算法,并将每个算法封装起来,使它们可以相互替换,且算法的变化不会影响使用算法的客户。策略模式属于对象行为模式,它通过对算法进行封装,把使用算法的责任和算法的实现分割开来,并委派给不同的对象对这些算法进行管理。

一个类中的一些行为,可能会随着系统的迭代而发生变化。为了使得该类满足开放-封闭原则(即:具备可扩展性 或 弹性),我们需要将这些未来会发生动态变化的行为从该类中剥离出来,并通过预测未来业务发展的方式,为这些行为抽象出共有的特征,封装在抽象类或接口中,并通过它们的实现类提供具体的行为。原本类中需要持有该抽象类/接口的引用。在使用时,将某一个具体的实现类对象注入给该类所持有的接口/抽象类的引用。

优点:

  1. 多重条件语句不易维护,而使用策略模式可以避免使用多重条件语句。
  2. 策略模式提供了一系列的可供重用的算法族,恰当使用继承可以把算法族的公共代码转移到父类里面,从而避免重复的代码。
  3. 策略模式可以提供相同行为的不同实现,客户可以根据不同时间或空间要求选择不同的。
  4. 策略模式提供了对开闭原则的完美支持,可以在不修改原代码的情况下,灵活增加新算法。
  5. 策略模式把算法的使用放到环境类中,而算法的实现移到具体策略类中,实现了二者的分离。

缺点:

  1. 客户端必须理解所有策略算法的区别,以便适时选择恰当的算法类。
  2. 策略模式造成很多的策略类。

模式结构

  1. 如果类A中有两个行为X和Y会随着业务的发展而变化,那么,我们需要将这两个行为从类A中剥离出来,并形成各自的继承体系(策略体系)。每个继承体系(策略体系)的顶层父类/接口中定义共有行为的抽象函数,每个子类/实现类中定义该策略体系具体的实现。其中,每一个被抽象出来的继承体系被称为一个策略体系,每个具体的实现类被称为策略
  2. 此时,策略体系已经构建完成,接下来需要改造类A。 在类A中增加所需策略体系的顶层父类/接口,并向外暴露一个共有的函数action给调用者使用。在Spring项目中,策略类和类A之间的依赖关系可以通过依赖注入来完成。

策略模式的优点详解

1. 满足开放封闭原则

如果类A需要更换一种策略的时候,只需修改Spring的XML配置文件即可,其余所有的代码均不需要修改。

比如,将类A的策略X_1更换成X_2的方法如下:

<bean id="a" class="类A">
    <!-- 将原本策略实现类X_1修改为策略实现类X_2即可 -->
    <property name="策略接口X" class="策略实现类X_2" />
</bean>

此外,如果需要新增一种策略,只需要为策略接口X添加一个新的实现类即可,并覆盖其中的commonAction函数。然后按照上面的方式修改XML文件即可。

在这个过程中,在保持原有Java代码不发生变化的前提下,扩展性了新的功能,从而满足开放封闭原则。

2. 可方便地创建具有不同策略的对象

如果我们需要根据不同的策略创建多种类A的对象,那么使用策略模式就能很容易地实现这一点。

比如,我们要创建三个A类的对象,a、b、c。其中,a使用策略X_1和Y_1,b使用策略X_2和Y_2,c使用策略X_3和Y_3。 
要创建这三个对象,我们只需在XML中作如下配置即可:

<bean id="a" class="类A">
    <property name="策略接口X" class="策略实现类X_1" />
    <property name="策略接口Y" class="策略实现类Y_1" />
</bean>

<bean id="b" class="类A">
    <property name="策略接口X" class="策略实现类X_2" />
    <property name="策略接口Y" class="策略实现类Y_2" />
</bean>

<bean id="c" class="类A">
    <property name="策略接口X" class="策略实现类X_3" />
    <property name="策略接口Y" class="策略实现类Y_3" />
</bean>

问:如何实现部分继承?也就是类Son1只继承Father的一部分功能,Son2继承Father的另一部分功能。

这是设计上的缺陷,当出现这种情况时,应当将父类再次拆分成2个子类,保证任何一个父类的行为和特征均是该继承体系中共有的!

问:随着需求的变化,父类中需要增加共有行为时怎么办?这就破坏了“开放封闭原则”。

这并未破坏“开放封闭原则”!在系统迭代更新的过程中,修改原有的代码是在所难免的,这并不违背“开放封闭原则”。 
“开放封闭原则”要求我们:当系统在迭代过程中,第一次出现某一类型的需求时,是允许修改的;在此时,应该对系统进行修改,并进行合理地设计,以保证对该类型需求的再次修改具备可扩展性。当再一次出现该类型的需求时,就不应该修改原有代码,只允许通过扩展来满足需求。

 

参考:

(1)柴毛毛大话设计模式——开发常用的设计模式梳理  https://blog.csdn.net/u010425776/article/details/79211117

(2)策略模式(策略设计模式)详解  http://c.biancheng.net/view/1378.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值