首先我们需要知道策略模式与状态模式是如此的相似,就犹如一对双胞胎一样。只不过状态模式是通过改变对象内部的状态来帮助对象控制自己的行为,而策略模式则是围绕可以互换的算法来创建成功业务的两者都可用于解决同一个问题:带有大量的if..else…等条件判断语句来进行选择的(小弟初学,不知这样理解是否有误??有误望指出…)。

在我们的生活中我们可以通过很多种不同的方式来完成一件事情,这里的每一种方式都可以称作为一种策略。我们可以根据环境、条件等因素的不同选择不同的策略来完成这件事情。比如说出去旅游,我们可以选择坐火车、坐飞机、坐大巴、骑自行车,甚至徒步等等方式。如果想舒适快速我们可以选择飞机,节约钱我们可以选择火车和大巴,离家近的我们可以骑自行车,每一种方式都可以到达目的地。但是总有一种方式是当前最适合你的。你会选择哪种出行方式呢?

在软件开发过程中是一样的,我们可能有很多种方法可以实现某一个功能,但是我们需要一种简单、高效的途径可以使得系统能够灵活的解决问题。这就是策略模式的设计动机。

一、模式定义

在前面中对策略模式应该有了一个最初步的认识。那么什么是策略模式呢?所谓策略模式就是定义了算法族,分别封装起来,让他们之前可以互相转换,此模式然该算法的变化独立于使用算法的客户。

在软件系统中有很多种方法可以实现同一个功能,比如排序算法它有冒泡排序、选择排序、快速排序、插入排序等等。这里我们有一种硬编码方法,就是讲所以的排序算法全部写在一个类中,每一种算法的具体实现对应着一个方法,然后写一个总方法通过if…else…来判断选择具体的排序算法,但是这样做存在几个问题。

第一:如果需要增加新的算法,则需要修改源代码。

第二:如果更新了排序算法,那么需要在客户端也需要修改代码,麻烦。

第三:充斥着大量的if…else…语句,代码维护比较困难。

所以为了解决这些问题,我们可以定义一些独立的类来封装不同的算法,每一个独立的类对应着一个具体的算法实现,在这里我们就将这里每一个独立的类称之为一个策略。

二、模式结构

下图为策略模式的结构:

这个UML图与状态模式的几乎一模一样,状态模式是通过改变对象内部的状态来帮助对象控制自己的行为,我们可以这样理解状态模式其实是对状态进行封装,它是将动作动作的实现和责任进行分割,把动作委托到代表当前状态的对象。而策略模式是对算法进行封装,把算法的责任和算法本身进行分割开来,同时委派给不同的对象进行管理。策略模式是将一个系列的算法封装到一系列的策略里面。

其实对于算法的选择,策略模式并不关心,它只是对算法进行封装,至于算法什么时候什么地方使用什么算法都是客户所决定的,这样就提高了系统的灵活性,但同时也增加了客户的负担,因为客户需要清楚知道选择什么样的算法对自己最有利,这就需要客户对每一个算法都清楚知道他们的区别。

三、模式实现

我们都知道排序算法有很多种,但是什么时候选择冒泡排序,什么时候选择选择排序,什么时候选择插入排序,所以这里用排序算法来演示策略模式的实现。 
      首先我们先来看看在没有使用策略模式的情况。

public void selectSort(String type){
if("type1".equals(type)){
//选择快速排序
}
else if("type2".equals(type)){
//选择插入排序
}
else if("type3".equals(type)){
//选择冒泡排序
}
else if("type4".equals(type)){
//选择选择排序
}
......
}

  对于这样的代码实现,除了代码中充斥着大量的if…else if…else,导致程序可维护性很差,而且系统的可扩展性不好,如果某个排序模块进行更改了,有可能需要修改源代码。所以在对于这样的情景是非常合适使用策略模式的。

那么如何使用策略模式呢?首先我们需要定义一个接口,该接口提供排序算法,然后定义想要的排序算法,实现给接口即可。如下:

首先是Sort接口,该接口定义了排序算法,所有的排序算法都应该实现该接口。

public interface Sort{
public abstract int[] sort(int arr[]);
}

然后是三个具体的排序算法,他们实现Sort接口。

冒泡排序:BubbleSort.java

public class BubbleSort implements Sort{
public int[] sort(int arr[]){
int len=arr.length;
for(int i=0;i<len;i++){
for(int j=i+1;j<len;j++){
int temp;
if(arr[i]>arr[j]){
temp=arr[j];
arr[j]=arr[i];
arr[i]=temp;
}
}
}
System.out.println("冒泡排序");
return arr;
}
}

插入排序:InsertionSort.java

public class InsertionSort implements Sort {
public int[] sort(int arr[]) {
int len = arr.length;
for (int i = 1; i < len; i++) {
int j;
int temp = arr[i];
for (j = i; j > 0; j--) {
if (arr[j - 1] > temp) {
arr[j] = arr[j - 1]; } else
break;
}
arr[j] = temp;
}
System.out.println("插入排序");
return arr;
}
}

选择排序:SelectSort.java

public class SelectionSort implements Sort {
public int[] sort(int arr[]) {
int len = arr.length;
int temp;
for (int i = 0; i < len; i++) {
temp = arr[i];
int j;
int samllestLocation = i;
for (j = i + 1; j < len; j++) {
if (arr[j] < temp) {
temp = arr[j];
samllestLocation = j;
}
}
arr[samllestLocation] = arr[i];
arr[i] = temp;
}
System.out.println("ѡ������");
return arr;
}
}

最后就是测试类客户端了Client.java

public class ArrayHandler
{
private Sort sortObj; public int[] sort(int arr[])
{
sortObj.sort(arr);
return arr;
} public void setSortObj(Sort sortObj) {
this.sortObj = sortObj;
}
}
public class Client
{
public static void main(String args[])
{
int arr[]={1,4,6,2,5,3,7,10,9};
int result[];
ArrayHandler ah=new ArrayHandler(); Sort sort = new SelectionSort(); //使用选择排序 ah.setSortObj(sort); //设置具体策略
result=ah.sort(arr); for(int i=0;i<result.length;i++)
{
System.out.print(result[i] + ",");
}
}
}

运行结果

選擇排序 
      1,2,3,4,5,6,7,9,10,

四、模式优缺点

优点

      1、策略模式提供了对“开闭原则”的完美支持,用户可以在不修改原有系统的基础上选择算法或行为,也可以灵活地增加新的算法或行为。 
      2、策略模式提供了可以替换继承关系的办法。 
      3、使用策略模式可以避免使用多重条件转移语句

缺点

      1、客户端必须知道所有的策略类,并自行决定使用哪一个策略类。 
      2、策略模式将造成产生很多策略类,

五、使用场景

1、如果在一个系统里面有许多类,它们之间的区别仅在于它们的行为,那么使用策略模式可以动态地让一个对象在许多行为中选择一种行为。 
      2、一个系统需要动态地在几种算法中选择一种。 
     3、如果一个对象有很多的行为,如果不用恰当的模式,这些行为就只好使用多重的条件选择语句来实现。

设计模式:策略模式(Stratege)的更多相关文章

  1. 15. 星际争霸之php设计模式--策略模式

    题记==============================================================================本php设计模式专辑来源于博客(jymo ...

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

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

  3. linkin大话设计模式--策略模式

    linkin大话设计模式--策略模式 Strategy [ˈstrætədʒi]  策略 策略模式用于封装系列的算法,这些算法通常被封装在一个称为Context的类中,客户端程序可以自由的选择任何一种 ...

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

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

  5. 设计模式-策略模式(Strategy Model)

    1.概述     在开发过程中常常会遇到类似问题,实现一个功能的时候往往有多种算法/方法(策略),我们可以根据环境的不同来使用不同的算法或策略来实现这一功能.     如在人物比较排序的实现中,我们有 ...

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

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

  7. [Head First设计模式]策略模式

    系列文章 [Head First设计模式]山西面馆中的设计模式——装饰者模式 [Head First设计模式]山西面馆中的设计模式——观察者模式 [Head First设计模式]山西面馆中的设计模式— ...

  8. javascript 设计模式-----策略模式

    在<javascript设计模式>中,作者并没有向我们介绍策略模式,然而它却是一种在开发中十分常见的设计模式.最常见的就是当我们遇到一个复杂的表单验证的时候,常常需要编写一大段的if和el ...

  9. JAVA 设计模式 策略模式

    用途 Title 它定义了算法家族,分别封装起来,让它们之间可以互相替换,此模式让算法的变化,不会影响到使用算法的客户. 策略模式是一种行为型模式. 结构

随机推荐

  1. 使用python 将地址链接变成二维码

    import os from MyQR import myqr myqr.run( words='https://sz.ke.com/?utm_source=baidu&utm_medium= ...

  2. AcWing:99. 激光炸弹(前缀和)

    一种新型的激光炸弹,可以摧毁一个边长为 RR 的正方形内的所有的目标. 现在地图上有 NN 个目标,用整数Xi,YiXi,Yi表示目标在地图上的位置,每个目标都有一个价值WiWi. 激光炸弹的投放是通 ...

  3. css 元素的竖向百分比设定是相对于容器的高度吗?

    结论是,如果是height的话,是相对于容器高度,如果是padding-height,margin-height则是相对于容器的宽度. 举例说明: <!DOCTYPE html> < ...

  4. 一步一步实现一个Promise A+规范的 Promise

    2015年6月,ES2015(即ES6)正式发布后受到了非常多的关注.其中很重要的一点是 Promise 被列为了正式规范. 在此之前很多库都对异步编程/回调地狱实现了类 Promise 的应对方案, ...

  5. win7远程连接ubuntu,出现灰屏解决方法

      问题: win7远程虚拟机ubuntu 12.04出现灰色屏幕 打开windows自带的远程桌面连接.输入ubuntu虚拟机的IP地址 可以连接上,输入username和password 点击OK ...

  6. Centos7 yum install chrome

    一.配置 yun 源 vim /etc/yum.repos.d/google-chrome.repo [google-chrome] name=google-chrome baseurl=http:/ ...

  7. jdk git maven Jenkins的配置

    前言 搭建Jenkins的笔记. JDK 1.  jdk 下载地址 https://www.oracle.com/technetwork/java/javase/downloads/jdk8-down ...

  8. LNMPA是什么?

    也许大家对LAMP.LNMP比较熟悉,LAMP代表Linux下Apache.MySQL.PHP这种网站服务器架构:LNMP代表的是Linux下Nginx.MySQL.PHP这种网站服务器架构.LNMP ...

  9. leetcode 207课程表

    class Solution { public: bool canFinish(int numCourses, vector<vector<int>>& prerequ ...

  10. Nginx服务应用

    虚拟主机 基于域名的虚拟主机 所谓基于域名的虚拟主机,意思就是通过不同的域名区分不同的虚拟主机,基于域名的虚拟主机是企业应用最广的虚拟主机类型,几乎所有对外提供服务的网站都是使用基于域名的虚拟主机 基 ...