策略模式定义了一系列的算法,并将每一个算法封装起来,而且使它们还可以相互替换。策略模式让算法独立于使用它的客户而独立变化.
(原文:The Strategy Pattern defines a family of algorithms,encapsulates each one,and makes them interchangeable.
Strategy lets the algorithm vary independently from clients that use it.)
策略模式的特点:
1 Context(应用实例或client, 即使用Strategy的类)持有一个Strategy实例;
2 Context可以动态灵活的设置Strategy的具体实例,即切换算法;
3 Context通过调用strategy的方法来执行具体的行为。
示例代码:
这个例子很抽象,大多数的设计模式书中都会给出这么个例子,这个例子不具备任何生产价值,于是我想到了一个更好的例子:
笔记本电脑中都有一个电源管理器,提供多种电源管理方案。每个方案都是一种策略,操作系统(或使用电脑的人)应该能灵活切换供电方案。下面用代码模拟:
- //策略接口
- package designpattern.strategy;
- public interface PowerStrategy {
- public void apply();
- }
- //引用实例,持有策略者
- package designpattern.strategy;
- public class Computer {
- private PowerStrategy ps;
- public PowerStrategy getPs() {
- return ps;
- }
- public void setPs(PowerStrategy ps) {
- this.ps = ps;
- }
- public void applyPowerStrategy(){
- ps.apply();
- }
- }
- //策略1 高表现性能策略
- package designpattern.strategy;
- public class HighPerformanceStrategy implements PowerStrategy{
- public void apply() {
- System.out.println("*** High performance power strategy ***");
- System.out.println("Turn off monitor: Never;");
- System.out.println("Turn off hard disk: Never;");
- System.out.println("System standby: Never;");
- System.out.println("System hibernates: Never./n");
- }
- }
- //策略2 中等策略
- package designpattern.strategy;
- public class MediumStragegy implements PowerStrategy{
- public void apply() {
- System.out.println("*** Medium power strategy ***");
- System.out.println("Turn off monitor: 1 hour;");
- System.out.println("Turn off hard disk: 2 hours;");
- System.out.println("System standby: 3 hours;");
- System.out.println("System hibernates: 4 hours./n");
- }
- }
- //策略3 节能策略
- package designpattern.strategy;
- public class EnergySavingStrategy implements PowerStrategy{
- public void apply() {
- System.out.println("*** Energy-saving strategy ***");
- System.out.println("Turn off monitor: 5 minutes;");
- System.out.println("Turn off hard disk: 15 minutes;");
- System.out.println("System standby: 30 minutes;");
- System.out.println("System hibernates: 1 hour./n");
- }
- }
- //测试用例
- package designpattern.strategy;
- public class Test {
- public static void main(String[] args){
- Computer c = new Computer();
- c.setPs(new HighPerformanceStrategy());
- c.applyPowerStrategy();
- c.setPs(new MediumStragegy());
- c.applyPowerStrategy();
- c.setPs(new EnergySavingStrategy());
- c.applyPowerStrategy();
- }
- }
经典案例:
1 jdk中的类File有一个方法:public String[] list(FilenameFilter filter),列出当前目录下的所有文件,FilenameFilter就是一个策略接口,使用者可以根据自己的需求自由变换文件筛选策略.
2 jdk中工具类Arrays有一个可以对集合排序的方法: public static <T> void sort(T[] a, Comparator<? super T> c),传入一个数组和一个比较器, 这个比较器就是一个策略.(此案有争议,有人认为是template method模式).
应用场景:
1 多个类只区别在表现行为不同,可以使用Strategy模式,在运行时动态选择具体要执行的行为;
2 需要在不同情况下使用不同的策略(算法)。
优点:
把容易发生变化的算法独立出来,易于扩展。
缺点:
类增多了,使系统难度加大。
- class StrategyExample {
- //test case.
- public static void main(String[] args) {
- Context context;
- // Three contexts following different strategies
- context = new Context(new FirstStrategy());
- context.execute();
- context = new Context(new SecondStrategy());
- context.execute();
- context = new Context(new ThirdStrategy());
- context.execute();
- }
- }
- // Strategy interface
- // The context class uses this to call the concrete strategy
- interface Strategy {
- void execute();
- }
- // Implements the algorithm using the strategy interface
- class FirstStrategy implements Strategy {
- public void execute() {
- System.out.println("Called FirstStrategy.execute()");
- }
- }
- class SecondStrategy implements Strategy {
- public void execute() {
- System.out.println("Called SecondStrategy.execute()");
- }
- }
- class ThirdStrategy implements Strategy {
- public void execute() {
- System.out.println("Called ThirdStrategy.execute()");
- }
- }
- // Configured with a ConcreteStrategy object and maintains a reference to a Strategy object
- class Context {
- Strategy strategy;
- // Constructor
- public Context(Strategy strategy) {
- this.strategy = strategy;
- }
- public void execute() {
- this.strategy.execute();
- }
- }