前言:在平时的项目开发中,如果遇到某个业务需要实现多种算法或者策略,而这些策略又时常发生变化,或者需要组合使用,如果将这些算法封装在一个类中,然后通过 if else选择,将导致该类臃肿不容易维护,任何一种算法的改变都会影响到其他算法,不符合面向对象的设计思路。
解决思路:把一个类中经常改变或者将来可能改变的部分提取出来,作为一个接口,然后在类中包含这个对象的实例,这样类的实例在运行时就可以随意调用实现了这个接口的类的行为。比如定义一系列的算法,把每一个算法封装起来, 并且使它们可相互替换,使得算法可独立于使用它的客户而变化。这就是策略模式。
下面是策略模式实现的类结构图:
● 环境(Context)角色:拥有一个Strategy的引用,。
● 抽象策略(Strategy)角色:这是一个抽象角色,通常由一个接口或抽象类实现。此角色给出所有的具体策略类所需的接口。
● 具体策略(ConcreteStrategy)角色:包装了相关的算法或行为。
public class Context {
//持有一个具体策略的对象
private Strategy strategy;
<span style="font-family:Helvetica, Tahoma, Arial, sans-serif;">//构造行数中具体传入什么策略,该类持有的对象就表现为对应的行为</span>
public Context(Strategy strategy){
this.strategy = strategy;
}
/**
* 策略方法
*/
public void contextInterface(){
strategy.strategyInterface();
}
}
策略方法抽象成的公共接口
public interface Strategy {
/**
* 策略方法
*/
public void strategyInterface();
}
下面分别是A,B,C三种策略方法
public class ConcreteStrategyA implements Strategy {
@Override
public void strategyInterface() {
//<span style="font-family:Helvetica, Tahoma, Arial, sans-serif;">A算法或策略</span>
}
}
public class ConcreteStrategy<span style="font-family:Helvetica, Tahoma, Arial, sans-serif;">B</span> implements Strategy {
@Override
public void strategyInterface() {
//<span style="font-family:Helvetica, Tahoma, Arial, sans-serif;">B算法或策略</span>
}
}
public class ConcreteStrategy<span style="font-family:Helvetica, Tahoma, Arial, sans-serif;">C</span> implements Strategy {
@Override
public void strategyInterface() {
//<span style="font-family:Helvetica, Tahoma, Arial, sans-serif;">C算法或策略</span>
}
}
客户端:选择策略
</pre><pre name="code" class="java">public <span style="font-family:Helvetica, Tahoma, Arial, sans-serif;">static void mian(String[] args){
Context ctx ;
ctx=new (new ConcreeteStrategyA()</span><span style="font-family:Helvetica, Tahoma, Arial, sans-serif;"> );
ctx.contextInterface();</span><span style="font-family:Helvetica, Tahoma, Arial, sans-serif;">
<span style="font-family:Helvetica, Tahoma, Arial, sans-serif;font-size:14px;"></span></span><pre name="code" class="java"><span style="font-family:Helvetica, Tahoma, Arial, sans-serif;"> ctx=new (new ConcreeteStrategyB()</span><span style="font-family:Helvetica, Tahoma, Arial, sans-serif;"> );
ctx.contextInterface();</span>
}
注: 客户端的选择策略的过程可以交给一个抽象工厂来做,这样客户端只要告诉工厂我需要什么策略就可以了,这样客户端的代码和逻辑就非常简单了