策略模式(Strategy Pattern)

一、模式动机

策略模式(Strategy Pattern)用于算法的自由切换和扩展,是一种使用较为广泛的行为型模式。策略模式对应于解决某一问题的一个算法族,允许用户从该算法族中任选一个算法解决某一问题,同时可以方便地更换算法或者增加新的算法。它将每一个算法封装在一个称为具体策略的类中,同时为其提供统一的抽象策略类,而使用这些算法完成某一业务功能的类称为环境类
策略模式实现了算法定义和算法使用的分离,它通过继承和多态的机制实现对算法族的使用和管理,是一种简单易用的对象行为型模式。

  • 实现某个目标的途径不止一条,可根据实际情况选择一条合适的途径
  • 软件开发:
    • 多种算法,例如排序、查找、打折等
    • 使用硬编码(Hard Coding)实现将导致系统违背开闭原则,扩展性差,且维护困难
  • 可以定义一些独立的类来封装不同的算法,每一个类封装一种具体的算法 ——> 策略类 ——> 策略模式

二、模式定义

  • 策略模式(Strategy Pattern):定义一系列算法,将每一个算法封装起来,并让它们可以相互替换。
  • 策略模式让算法独立于使用它的客户而变化
  • 又称为政策(Policy)模式
  • 每一个封装算法的类称之为策略(Strategy)类
  • 策略模式提供了一种可插入式(Pluggable)算法的实现方案
  • 策略模式是一种对象行为型模式

三、模式结构

image


抽象策略类

public abstract class Strategy {
    public abstract void algorithm( );  //声明抽象算法
}

具体策略类

public class ConcreteStrategyA extends Strategy {
    //算法的具体实现
    public void algorithm( ) {
        //算法A
    }
}

环境类

public class Context {
    private Strategy strategy; //维持一个对抽象策略类的引用
    //注入策略对象
    public void setStrategy(Strategy strategy) {
        this.strategy= strategy;
    }
    //调用策略类中的算法
    public void algorithm( ) {
        strategy.algorithm( );
    }
}

客户类

……
Context context = new Context( );
Strategy strategy;
strategy = new ConcreteStrategyA( );
             //可在运行时指定类型,通过配置文件和反射机制实现
context.setStrategy(strategy);
context.algorithm( );
……

四、案例实现

案例背景

旅游选择不同的出行方式

案例结构

image

代码实现

环境类:Persion

public class Person {

    private TravelStrategy strategy;

    public void setStrategy(TravelStrategy strategy) {
        this.strategy = strategy;
    }

    public void travel(){
        strategy.travel();
    }
}

抽象策略类

public interface TravelStrategy {

    void travel();

}

具体策略类

public class BicycleStrategy implements TravelStrategy{
    @Override
    public void travel() {
        System.out.println("自行车游!");
    }
}

具体策略类

public class WorkStrategy implements TravelStrategy{
    @Override
    public void travel() {
        System.out.println("徒步旅行!");
    }
}

具体策略类

public class TrainStrategy implements TravelStrategy{
    @Override
    public void travel() {
        System.out.println("乘火车旅行!");
    }
}

具体策略类

public class AirplaneStategy implements TravelStrategy{
    @Override
    public void travel() {
        System.out.println("飞机旅行!");
    }
}

客户类

public class Client {
    public static void main(String[] args) {

        Person person = new Person();
        TravelStrategy strategy = (TravelStrategy) XMLUtil.getBean();
        person.setStrategy(strategy);
        person.travel();
    }

}

五、总结

模式优点

  • 提供了对开闭原则的完美支持,用户可以在不修改原有系统的基础上选择算法或行为,也可以灵活地增加新的算法或行为
  • 提供了管理相关的算法族的办法
  • 提供了一种可以替换继承关系的办法
  • 可以避免多重条件选择语句
  • 提供了一种算法的复用机制,不同的环境类可以方便地复用策略类

模式缺点

  • 客户端必须知道所有的策略类,并自行决定使用哪一个策略类
  • 将造成系统产生很多具体策略类
  • 无法同时在客户端使用多个策略类

使用情形

  • 一个系统需要动态地在几种算法中选择一种
  • 避免使用难以维护的多重条件选择语句
  • 不希望客户端知道复杂的、与算法相关的数据结构,提高算法的保密性与安全性
posted @ 2023-05-22 20:33  街酒  阅读(69)  评论(0编辑  收藏  举报
Title