博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
策略模式——对象行为模式
阅读量:2381 次
发布时间:2019-05-10

本文共 3149 字,大约阅读时间需要 10 分钟。

意图

策略模式定义了一系列的算法,并将每一个算法封装起来,而且使它们还可以相互替换。策略模式让算法独立于使用它的客户而独立变化。


适用性

当存在以下情况时使用Strategy模式

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


结构图

这里写图片描述

角色

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

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


优缺点

优点

1) 相关算法系列 Strategy类层次为Context定义了一系列的可供重用的算法或行为。 继承有助于析取出这些算法中的公共功能。

2) 提供了可以替换继承关系的办法: 继承提供了另一种支持多种算法或行为的方法。你可以直接生成一个Context类的子类,从而给它以不同的行为。但这会将行为硬行编制到 Context中,而将算法的实现与Context的实现混合起来,从而使Context难以理解、难以维护和难以扩展,而且还不能动态地改变算法。最后你得到一堆相关的类 , 它们之间的唯一差别是它们所使用的算法或行为。 将算法封装在独立的Strategy类中使得你可以独立于其Context改变它,使它易于切换、易于理解、易于扩展。
3) 消除了一些if else条件语句 :Strategy模式提供了用条件语句选择所需的行为以外的另一种选择。当不同的行为堆砌在一个类中时 ,很难避免使用条件语句来选择合适的行为。将行为封装在一个个独立的Strategy类中消除了这些条件语句。含有许多条件语句的代码通常意味着需要使用Strategy模式。
4) 实现的选择 Strategy模式可以提供相同行为的不同实现。客户可以根据不同时间 /空间权衡取舍要求从不同策略中进行选择。

缺点

1)客户端必须知道所有的策略类,并自行决定使用哪一个策略类: 本模式有一个潜在的缺点,就是一个客户要选择一个合适的Strategy就必须知道这些Strategy到底有何不同。此时可能不得不向客户暴露具体的实现问题。因此仅当这些不同行为变体与客户相关的行为时 , 才需要使用Strategy模式。

2 ) Strategy和Context之间的通信开销 :无论各个ConcreteStrategy实现的算法是简单还是复杂, 它们都共享Strategy定义的接口。因此很可能某些 ConcreteStrategy不会都用到所有通过这个接口传递给它们的信息;简单的 ConcreteStrategy可能不使用其中的任何信息!这就意味着有时Context会创建和初始化一些永远不会用到的参数。如果存在这样问题 , 那么将需要在Strategy和Context之间更进行紧密的耦合。
3 )策略模式将造成产生很多策略类:可以通过使用享元模式在一定程度上减少对象的数量。 增加了对象的数目 Strategy增加了一个应用中的对象的数目。有时你可以将 Strategy实现为可供各Context共享的无状态的对象来减少这一开销。任何其余的状态都由 Context维护。Context在每一次对Strategy对象的请求中都将这个状态传递过去。共享的 Strategy不应在各次调用之间维护状态。


实现

这里写图片描述

代码

/** * 出行旅游 * *  */  interface TravelStrategy{      public void travelAlgorithm();  }   /**  * 具体策略类(ConcreteStrategy)1:乘坐飞机  */  class AirPlanelStrategy Implements TravelStrategy {      public void travelAlgorithm(){          System.out.println( "travel by AirPlain");       }  }   /**  * 具体策略类(ConcreteStrategy)2:乘坐火车  */  class TrainStrategy implements TravelStrategy {      public void travelAlgorithm(){          System.out.println("travel by Train");       }  }   /**  * 具体策略类(ConcreteStrategy)3:骑自行车  */  class BicycleStrategy implements TravelStrategy {      public void travelAlgorithm(){          System.out.println("travel by Bicycle");       }  }   /**  *   * 环境类(Context):用一个ConcreteStrategy对象来配置。维护一个对Strategy对象的引用。可定义一个接口来让Strategy访问它的数据。  * 算法解决类,以提供客户选择使用何种解决方案:  */  class PersonContext{      private strategy = null;      public coid PersonContext(TravelStrategy travel){          this.strategy = travel;      }      public void  setTravelStrategy(TravelStrategy travel){        this.strategy = travel;      }      /**     * 旅行     */      public void travel(){          return this.strategy.travelAlgorithm();      }  }   public class Client {
public static void main(String[] args) { // 乘坐火车旅行 PersonContext person = new PersonContext(new TrainStrategy()); person.travel(); // 改骑自行车 person.setTravelStrategy(new BicycleStrategy()); person.travel(); }}
你可能感兴趣的文章
netcdf源码在windows上的编译
查看>>
慎用VC 6.0
查看>>
游戏杆编程心得
查看>>
周例会的作用
查看>>
字符集研究之多字节字符集和unicode字符集
查看>>
字符集研究之不同字符集的转换方式
查看>>
参观广东省博物馆
查看>>
C#调用C库的注意事项
查看>>
游戏杆编程心得二:如何判断按钮的有效按下
查看>>
一个应用程序无法启动错误的解决过程
查看>>
除虫记——有关WindowsAPI文件查找函数的一次压力测试
查看>>
Incredibuild导入key的方式
查看>>
跨平台C++开源代码的两种常用编译方式
查看>>
VC和MATLAB混合开发需要注意的一个问题
查看>>
成都一日游
查看>>
清明节太原两日游
查看>>
Java学习笔记(一)
查看>>
关于IT公司招聘的一个思考
查看>>
C#调用C++接口返回字符串的做法
查看>>
未能返回新代码元素错误的解决
查看>>