一、类图
二、模式含义
在策略模式结构图中包含如下几个角色:
Context(环境类):环境类是使用算法的角色,它在解决某个问题(即实现某个方法)时可以采用多种策略。在环境类中维持一个对抽象策略类的引用实例,用于定义所采用的策略。
Strategy(抽象策略类):它为所支持的算法声明了抽象方法,是所有策略类的父类,它可以是抽象类或具体类,也可以是接口。环境类通过抽象策略类中声明的方法在运行时调用具体策略类中实现的算法。
ConcreteStrategy(具体策略类):它实现了在抽象策略类中声明的算法,在运行时,具体策略类将覆盖在环境类中定义的抽象策略类对象,使用一种具体的算法实现某个业务处理。
三、代码实现
Strategy(抽象策略类)
package com.yan.pattern.strategy;
public abstract class Strategy {
public abstract void algorithm();
}
ConcreteStrategy(具体策略类)
package com.yan.pattern.strategy;
public class ConcreteStrategyA extends Strategy{
@Override
public void algorithm() {
System.out.println("策略A");
}
}
package com.yan.pattern.strategy;
public class ConcreteStrategyB extends Strategy{
@Override
public void algorithm() {
System.out.println("策略B");
}
}
Context(环境类)
package com.yan.pattern.strategy;
public class Context {
Strategy strategy;
public void setStrategy(Strategy strategy) {
this.strategy = strategy;
}
public void algorithm() {
System.out.println("准备开始计算");
strategy.algorithm();
System.out.println("计算结束");
}
}
客户端测试
package com.yan.pattern.strategy;
import java.awt.CardLayout;
import java.awt.Container;
import java.awt.GridLayout;
class Client {
public static void main(String args[]) {
Context context = new Context();
//策略A
Strategy strategy = new ConcreteStrategyA();
context.setStrategy(strategy);
context.algorithm();
//策略B
// Strategy strategy = new ConcreteStrategyB();
// context.setStrategy(strategy);
// context.algorithm();
}
}
四、总结
在以下情况下可以考虑使用策略模式:
(1) 一个系统需要动态地在几种算法中选择一种,那么可以将这些算法封装到一个个的具体算法类中,而这些具体算法类都是一个抽象算法类的子类。换言之,这些具体算法类均有统一的接口,根据“里氏代换原则”和面向对象的多态性,客户端可以选择使用任何一个具体算法类,并只需要维持一个数据类型是抽象算法类的对象。
(2) 一个对象有很多的行为,如果不用恰当的模式,这些行为就只好使用多重条件选择语句来实现。此时,使用策略模式,把这些行为转移到相应的具体策略类里面,就可以避免使用难以维护的多重条件选择语句。
(3) 不希望客户端知道复杂的、与算法相关的数据结构,在具体策略类中封装算法与相关的数据结构,可以提高算法的保密性与安全性。