设计模式 六月 03, 2021

策略模式

文章字数 4.1k 阅读约需 4 mins. 阅读次数 0

策略模式

解决问题

算法和对象分开来,使得算法可以独立于使用它的客户

方案

一系列的算法,把每一个算法封装起来, 并且使它们可相互替换。本模式使得算法可独立于使用它的客户而变化。

结构

策略模式

  • 环境类(Context): 用一个ConcreteStrategy对象来配置。维护一个对Strategy对象的引用。可定义一个接口来让Strategy访问它的数据。

  • 抽象策略类(Strategy): 定义所有支持的算法的公共接口。 Context使用这个接口来调用某ConcreteStrategy定义的算法。

  • 具体策略类(ConcreteStrategy): 以Strategy接口实现某具体算法.

适用性

  • 许多相关的类仅仅是行为有异。 “策略”提供了一种用多个行为中的一个行为来配置一个类的方法。即一个系统需要动态地在几种算法中选择一种。
  • 需要使用一个算法的不同变体。例如,你可能会定义一些反映不同的空间 /时间权衡的算法。当这些变体实现为一个算法的类层次时 ,可以使用策略模式。
  • 算法使用客户不应该知道的数据。可使用策略模式以避免暴露复杂的、与算法相关的数据结构。
  • 一个类定义了多种行为 , 并且这些行为在这个类的操作中以多个条件语句的形式出现。将相关的条件分支移入它们各自的Strategy类中以代替这些条件语句。

优缺点

优点:

  • 代码复用: Strategy类层次为Context定义了一系列的可供重用的算法或行为。 继承有助于析取出这些算法中的公共功能。
  • 提供了可以替换继承关系的办法: 将算法封装在独立的Strategy类中使得你可以独立于其Context改变它,使它易于切换、易于理解、易于扩展。
  • 消除了一些if else条件语句: Strategy模式提供了用条件语句选择所需的行为以外的另一种选择。
  • 实现的选择: Strategy模式可以提供相同行为的不同实现。客户可以根据不同时间 /空间权衡取舍要求从不同策略中进行选择。

缺点:

  • 客户端必须知道所有的策略类,并自行决定使用哪一个策略类,就是一个客户要选择一个合适的Strategy就必须知道这些Strategy到底有何不同。
  • Strategy和Context之间的通信开销 , 无论各个ConcreteStrategy实现的算法是简单还是复杂, 它们都共享Strategy定义的接口。因此很可能某些 ConcreteStrategy不会都用到所有通过这个接口传递给它们的信息;
  • 策略模式将造成产生很多策略类,.

经典实现

出门旅游

策略模式-出门旅游

/**
* 策略模式
* 定义一系列的算法,把每一个算法封装起来, 并且使它们可相互替换。本模式使得算法可独立于使用它的客户而变化
*
*/ 
 
/**
* 出行旅游
*
* 
*/
interface TravelStrategy{
    public void travelAlgorithm();
} 
 
 
/**
 * 具体策略类(ConcreteStrategy)1:乘坐飞机
 */
class AirPlanelStrategy implements TravelStrategy {
    
    @Override
    public void travelAlgorithm(){
        System.out.println("坐飞机"); 
    }
} 
 
 
/**
 * 具体策略类(ConcreteStrategy)2:乘坐火车
 */
class TrainStrategy implements TravelStrategy {
    @Override
    public void travelAlgorithm(){
        System.out.println("坐火车");
    }
} 
 
/**
 * 具体策略类(ConcreteStrategy)3:骑自行车
 */
class BicycleStrategy implements TravelStrategy {
    public void travelAlgorithm(){
        System.out.println("骑自行车");
    }
} 
/**
 * 
 * 环境类(Context):用一个ConcreteStrategy对象来配置。维护一个对Strategy对象的引用。可定义一个接口来让Strategy访问它的数据。
 * 算法解决类,以提供客户选择使用何种解决方案:
 */
class PersonContext{

    TravelStrategy tracelStrategy;
     // 设置出行策略
    public void setTravelStrategy(TravelStrategy tracelStrategy){
        this.tracelStrategy = tracelStrategy;
    }
    // 出行
    public void travelStrategy(){
        tracelStrategy.travelStyle();
    }
    
    public static void main(String[] args){
        Traveler traveler = new Travler();
        //游客设置出行策略
        traveler.setTravelsstrategy(new BicycleStrategy());
        
        // 执行出行
        traveler.travelStrategy();
    }
    
} 

目前实现过的

统一的导出模块的使用.定义exportService接口,不同表的导出创建不同exportService的实现.并service(‘别名’).通过@Autowired Map<String,exportService> 可以将策略根据别名统一收集,然后根据调用的不同参数,选择不同的策略来导出.

不同的登入策略接口.定义login接口多实现.根据不同的登入参数调用不同的接口实现.

0%