1、概述

    在开发过程中常常会遇到类似问题,实现一个功能的时候往往有多种算法/方法(策略),我们可以根据环境的不同来使用不同的算法或策略来实现这一功能。
    如在人物比较排序的实现中,我们有时需要把年龄做为比较的标准,或者有时又想将身高作为比较的标准,不同的比较标准也就衍生出了统一个比较目的的不同算法实现,在搜索问题中也是类似,有可能用到二分查找、顺序查找之类。通常较简单直接的思维便是将所有的算法(策略)写成一个类的方法,再通过客户端去调用;也可一将所有的算法全部封装在一个方法中用一堆的if...else...语句来判断。如果需要增加一种算法时,就需要去修改封装算法类的源代码;更换比较排序算法时,又需要去修改客户端代码。在算法类中封装了大量的算法,该类代码较复杂,维护困难;而且将策略包含在客户端,将导致客户端的程序庞大难以维护。
 
案例:出行旅游:出行旅游时,我们有以下几个策略可供选择:自行车、汽车、火车、飞机等,不同的方式,单都是去实现旅行这一个目的,选择策略的依据是时间、金钱、方便程度(对应到工程中就是需求的环境)。
 

2、目的

    策略模式的目的在于:使算法和对象分离开来,能让算法独立于对象去变化。
    核心思想其实是利用了面向对象编程多态的使用。
 

3、适用场景

    当存在一下情况时使用Strategy模式:
  1)许多类实现统一目的,仅方式不同。“策略”提供了一种用多个行为中的一种来配置类的实现的方法,及一个系统可以动态的在多个算法中选择其中一种;
  2)需要同一中算法的不同变体。如:在比较对象时,采用的比较算法的不同,有可能需要去比较对象的成员变量;
  3)一个类或者方法中定义了多种行为,并且这些行为以多个判断语句来相互切换。可将相关的条件分支移入各自的Strategy类中去实现。
  4)算法的封装。通过策略模式向使用算法的客户隐藏算法的具体实现。
 

4、结构与组成

  策略模式的结构主要分类三个部分:
  抽象策略类(Strategy):定义所有实现算法的公共接口,Context直接使用接口调用ConcreteStrategy的具体算法。
  具体策略类(ConcreteStrategy):实现具体的算法,每个具体的算法类必须实现Strategy接口。
  环境类(Context):具体算法的使用类,需要用指定的一个ConcreteStrategy来配置。

 

4、实现

  一个班级的若干个学生,对他们进行排序分别按照名字、年龄、id排序(正序和倒序两种方式),如年龄和名字重复,则使用id进行升序排序。
 package com.cnblogs.vicentzh.strategymodel;

 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.Comparator;
 import java.util.Iterator;
 import java.util.List;

 public class StrategyModel
 {
     /**
      * @Describe 客户端程序
      * @param args
      */
     public static void main(String[] args)
     {
         Student p1 = new Student("Tom",1,20);
         Student p2 = new Student("Tonny",2,50);
         Student p3 = new Student("Tom",5,30);
         Student p4 = new Student("John",8,10);
         Student p5 = new Student("Susan",9,15);

         List<Student> students = new ArrayList<Student>();
         students.add(p1);
         students.add(p2);
         students.add(p3);
         students.add(p4);
         students.add(p5);

         Context env = new Context();

         //正序排列
         UpNameSort uns = new UpNameSort();
         env.setSortStrategy(uns);
         env.sort(students);

         for (Iterator<Student> iter=students.iterator(); iter.hasNext();)
         {
             Student student = iter.next();
             System.out.println("id: " + student.getId() + ", name: " + student.getName()
                     + ", age:" + student.getAge());
         }
         System.out.println("-----------------------");

         //倒序排列
         DownNameSort dns = new DownNameSort();
         env.setSortStrategy(dns);
         env.sort(students);

         for (Iterator<Student> iter=students.iterator(); iter.hasNext();)
         {
             Student student = iter.next();
             System.out.println("id: " + student.getId() + ", name: " + student.getName()
                     + ", age:" + student.getAge());
         }

     }
 }

 //需要用到的具体实例类
 class Student
 {
     private String name;
     private int age;
     private int id;

     public Student(String name, int age, int id)
     {
         this.name = name;
         this.age = age;
         this.id = id;
     }

     public String getName()
     {
         return name;
     }
     public int getAge()
     {
         return age;
     }
     public int getId()
     {
         return id;
     }
 }

 //抽象策略类(Strategy),即策略接口
 interface SortStrategy
 {
     public void sortStudent(List<Student> students);
 }

 //具体策略类(ConcreteStrategy),即具体正序算法实现类
 class UpNameSort implements SortStrategy,Comparator<Student>
 {
     @Override
     public void sortStudent(List<Student> students)
     {
         Collections.sort(students, this);
     }

     @Override
     public int compare(Student o1, Student o2)
     {
         int result = o1.getName().compareTo(o2.getName());
         if(0==result)
         {
             return o1.getId() - o2.getId();
         }
         return result;
     }
 }

 //具体策略类(ConcreteStrategy),即具体倒序算法实现类
 class DownNameSort implements SortStrategy, Comparator<Student>
 {
     @Override
     public void sortStudent(List<Student> students)
     {
         Collections.sort(students, this);

     }

     @Override
     public int compare(Student o1, Student o2)
     {
         int result = o2.getName().compareTo(o1.getName());
         if(0==result)
         {
             return o1.getId() - o2.getId();
         }
         return result;
     }
 }

 //使用环境类(Context)
 //环境类根据接收到客户端具体的策略来对对象进行使用,同样也能用setSortStrategy方法
 //随时根据客户端的需求去改变策略算法,并且不影响对象。
 class Context
 {
     private SortStrategy concreteStrategy; //使用策略配置环境类

     public Context(SortStrategy conSortStrategy)
     {
         this.concreteStrategy = conSortStrategy;
     }

     public Context()
     {

     }

     //可随意定制化具体策略
     public void setSortStrategy(SortStrategy conSortStrategy)
     {
         this.concreteStrategy = conSortStrategy;
     }

     //使用具体的策略(concreteStrategy)对对象进行操作
     public void sort(List<Student> students)
     {
         concreteStrategy.sortStudent(students);
     }
 }

5、优缺点

  Strategy模式的优点:
  1)Strategy类将具体的算法进行抽象,为Context类提供了一系列可重用的算法或行为,同时屏蔽了底层算法实现的细节,同样也提高了代码的可重用性。
  2)通过Strategy模式,将具体策略的实现与应用的对象隔离开来,实现行为与对象的解耦;这样能是应用对象动态便捷的动态改变行为,使得算法易于切换、易于理解、易于扩展;
  3)消除了大量if...else...代码的冗余性和复杂性,以行为封装的形式使代码的逻辑表达更为清晰。
 
  Strategy模式的缺点:
  1)客户端必须知道所有的策略类,并自行决定使用哪一个策略类:  模式的潜在缺点就是一个客户要选择一个合适的Strategy就必须知道这些Strategy到底有何不同。此时可能不得不向客户暴露具体的实现问题。
  2)Strategy和Context之间的通信开销 :无论各个ConcreteStrategy实现的算法是简单还是复杂, 它们都共享Strategy定义的接口。因此很可能某些 ConcreteStrategy不会都用到所有通过这个接口传递给它们的信息;简单的 ConcreteStrategy可能不使用其中的任何信息!这就意味着有时Context会创建和初始化一些永远不会用到的参数。
  3)策略模式将造成产生很多策略类:可以通过使用享元模式在一定程度上减少对象的数量。 增加了对象的数目 Strategy增加了一个应用中的对象的数目。
 

6、总结分析

  1)策略模式是一个比较容易理解和使用的设计模式,策略模式是对算法的封装,它把算法的实现和算法的使用对象解耦,委派给不同的对象管理。策略模式通常把一个系列的算法封装到一系列的策略类里面,作为一个抽象策略类的子类。用一句话来说,就是“准备一组算法,并将每一个算法封装起来,使得它们可以互换”。

  2)策略模式仅仅封装算法,提供新算法插入到已有系统中,以及老算法从系统中“换代”和“退休”的方便。
  3)在策略模式中,策略模式并不决定在何时使用何种算法,算法的选择由客户端来决定。这在一定程度上提高了系统的灵活性,但是客户端需要理解所有具体策略类之间的区别,以便选择合适的算法,这也是策略模式的缺点之一,在一定程度上增加了客户端的使用难度。
 
 
 
 

作者:vincentzh

出处:http://www.cnblogs.com/vincentzh/

本文以学习、研究和分享为主,如需转载,请联系本人,标明作者和出处,非商业用途!

设计模式-策略模式(Strategy Model)的更多相关文章

  1. [.net 面向对象程序设计深入](26)实战设计模式——策略模式 Strategy (行为型)

    [.net 面向对象程序设计深入](26)实战设计模式——策略模式 Strategy (行为型) 1,策略模式定义 策略模式定义了一系列的算法,并将每一个算法封装起来,而且使它们还可以相互替换.策略模 ...

  2. 设计模式 - 策略模式(Strategy Pattern) 具体解释

    策略模式(Strategy Pattern) 具体解释 本文地址: http://blog.csdn.net/caroline_wendy/article/details/26577879 本文版权全 ...

  3. 设计模式--策略模式(strategy)

    1.策略模式(strategy ['strætədʒi]) 我的理解是:方案候选模式 (反正关键就是有很多的候选,哈哈) 看了很多例子,都是在说鸭子的,那个例子很好,在这里可以看 他们生产鸭子,我们就 ...

  4. java设计模式 策略模式Strategy

    本章讲述java设计模式中,策略模式相关的知识点. 1.策略模式定义 策略模式,又叫算法簇模式,就是定义了不同的算法族,并且之间可以互相替换,此模式让算法的变化独立于使用算法的客户.策略模式属于对象的 ...

  5. 设计模式——策略模式(Strategy Pattern)

    写在前面: 直接将书中的例子用来作为记录自己学习的成果,不知道这样好不好,如果给原作者带来什么不利的影响不妨告知一声,我及时删掉. UML图: 抽象策略:Strategy package com.cn ...

  6. 说说设计模式~策略模式(Strategy)

    返回目录 策略模式定义了一系列的算法,并将每一个算法封装起来,而且使它们还可以相互替换.而对于客户端(UI)来说,可以通过IOC再配合工厂模块,实现动态策略的切换,策略模块通常于一个抽象策略对象(in ...

  7. C#设计模式——策略模式(Strategy Pattern)

    一.概述我们来实现一个企业的工资系统,该企业中不同级别的员工工资算法都不相同,针对该问题,最容易想到的莫过于在代码中堆积一大堆if…else…语句或者是switch…case…语句.如果该企业中不同级 ...

  8. 设计模式-策略模式Strategy以及消灭if else

    概述 如果在开发过程中,出现大量的if else或者switch case 语句,如果这些语句块中的代码并不是包含业务逻辑,只是单纯的分流方法,那么,每一个语句块中都是一个算法或者叫策略. 背景 比如 ...

  9. 设计模式---策略模式Strategy(对象行为型)

    1. 概述 策略模式定义了一系列的算法,并将每一个算法封装起来,而且使它们还可以相互替换.策略模式让算法独立于使用它的客户而独立变化. 策略模式是对算法的封装,它把算法的责任和算法本身分割开,委派给不 ...

  10. 大话设计模式--策略模式 strategy -- C++实现实例

    1. 策略模式: 它定义了算法家族, 分别封装起来,使他们之间可以相互替换,此模式让算法变化, 不会影响到使用算法的客户. 用相同的方法调用不同的算法,减少各种算法类与使用算法类之间的耦合. 实例中策 ...

随机推荐

  1. 编译器开发系列--Ocelot语言6.静态类型检查

    关于"静态类型检查",想必使用C 或Java 的各位应该非常熟悉了.在此过程中将检查表达式的类型,发现类型不正确的操作时就会报错.例如结构体之间无法用+ 进行加法运算,指针和数值之 ...

  2. Hibernate 系列 学习笔记 目录 (持续更新...)

    前言: 最近也在学习Hibernate,遇到的问题差不多都解决了,顺便把学习过程遇到的问题和查找的资料文档都整理了一下分享出来,也算是能帮助更多的朋友们了. 最开始使用的是经典的MyEclipse,后 ...

  3. Linux设备管理(四)_从sysfs回到ktype

    sysfs是一个基于ramfs的文件系统,在2.6内核开始引入,用来导出内核对象(kernel object)的数据.属性到用户空间.与同样用于查看内核数据的proc不同,sysfs只关心具有层次结构 ...

  4. 项目游戏开发日记 No.0x000001

    14软二杨近星(2014551622) 既然已经决定了开发软件, 时不时就要练练手, 还要时不时的去寻找素材, 因为开发的人物设定就是DotA2里面的祈求者, 所以, 就去找了他的相关人物图片和模型, ...

  5. java 泛型

    1.Student stu =tool.getObj();右边得到的是Object类型,需要向下转型,强转换. 2. 3. 4.泛型方法不能被静态修饰这样写 5.如果想定义定义静态泛型方法,只能这样写 ...

  6. Fedora 22中的Services and Daemons

    Introduction Maintaining security on your system is extremely important, and one approach for this t ...

  7. MapReduce剖析笔记之六:TaskTracker初始化任务并启动JVM过程

    在上面一节我们分析了JobTracker调用JobQueueTaskScheduler进行任务分配,JobQueueTaskScheduler又调用JobInProgress按照一定顺序查找任务的流程 ...

  8. OAuth认证原理及HTTP下的密码安全传输

    很多人都会问这样一个问题,我们在登录的时候,密码会不会泄露?随便进一个网站,登录时抓包分析,可以看到自己的密码都是明文传输的,在如此复杂的web环境下,我们没有百分的把握保证信息在传输过程中不被截获, ...

  9. ABP框架 - 设置管理

    文档目录 本节内容: 简介 关于ISettingStore 定义设置 setting scope(设置范围) 重写设置定义 获取设置值 服务端 客户端 修改设置 关于缓存 简介 每个应用必需存储一些设 ...

  10. [翻译]AKKA笔记 - ACTOR生命周期 - 基本 -5

    原文地址:http://rerun.me/2014/10/21/akka-notes-actor-lifecycle-basic/ (请注意这了讨论的生命周期并不包括 preRestart 或者pos ...