设计模式:策略模式避免多重分支语句(ifelse)

一、定义

定义一族算法类,将每个算法分别封装起来,让它们可以互相替换。策略模式可以使算法的变化独立于使用它们的客户端(这里的客户端代指使用算法的代码)。

策略模式用来解耦策略的定义、创建、使用。实际上,一个完整的策略模式就是由这三个部分组成的。

二、原始类图

(1)抽象策略(Strategy)类:定义了一个公共接口,各种不同的算法以不同的方式实现这个接口,环境角色使用这个接口调用不同的算法,一般使用接口或抽象类实现。

(2)具体策略(Concrete Strategy)类:实现了抽象策略定义的接口,提供具体的算法实现。

(3)环境(Context)类:持有一个策略类的引用,最终给客户端调用。

三、案例

1、需求

希望写一个小程序,实现对一个文件进行排序的功能。文件中只包含整型数,并且,相邻的数字通过逗号来区隔。

2、需求分析

你可能会说,这不是很简单嘛,只需要将文件中的内容读取出来,并且通过逗号分割成一个一个的数字,放到内存数组中,然后编写某种排序算法(比如快排),或者直接使用编程语言提供的排序函数,对数组进行排序,最后再将数组中的数据写入文件就可以了。

但是,如果文件很大呢?比如有10GB大小,因为内存有限(比如只有8GB大小),我们没办法一次性加载文件中的所有数据到内存中,这个时候,我们就要利用外部排序算法了。

如果文件更大,比如有100GB大小,我们为了利用CPU多核的优势,可以在外部排序的基础之上进行优化,加入多线程并发排序的功能,这就有点类似“单机版”的MapReduce。

如果文件非常大,比如有1TB大小,即便是单机多线程排序,这也算很慢了。这个时候,我们可以使用真正的MapReduce框架,利用多机的处理能力,提高排序的效率。

3、代码实现

public interface ISortAlg {
    void sort(String filePath);
}

public class QuickSort implements ISortAlg {
    @Override
    public void sort(String filePath) {
        //...
    }
}

public class ExternalSort implements ISortAlg {
    @Override
    public void sort(String filePath) {
        //...
    }
}

public class ConcurrentExternalSort implements ISortAlg {
    @Override
    public void sort(String filePath) {
        //...
    }
}

public class MapReduceSort implements ISortAlg {
    @Override
    public void sort(String filePath) {
        //...
    }
}

public class Sorter {
  private static final long GB = 1000 * 1000 * 1000;
  private static final List algs = new ArrayList<>();
  static {
    algs.add(new AlgRange(0, 6*GB, SortAlgFactory.getSortAlg("QuickSort")));
    algs.add(new AlgRange(6*GB, 10*GB, SortAlgFactory.getSortAlg("ExternalSort")));
    algs.add(new AlgRange(10*GB, 100*GB, SortAlgFactory.getSortAlg("ConcurrentExternalSort")));
    algs.add(new AlgRange(100*GB, Long.MAX_VALUE, SortAlgFactory.getSortAlg("MapReduceSort")));
  }

  public void sortFile(String filePath) {
    // 省略校验逻辑
    File file = new File(filePath);
    long fileSize = file.length();
    ISortAlg sortAlg = null;
    for (AlgRange algRange : algs) {
      if (algRange.inRange(fileSize)) {
        sortAlg = algRange.getAlg();
        break;
      }
    }
    sortAlg.sort(filePath);
  }

  private static class AlgRange {
    private long start;
    private long end;
    private ISortAlg alg;

    public AlgRange(long start, long end, ISortAlg alg) {
      this.start = start;
      this.end = end;
      this.alg = alg;
    }

    public ISortAlg getAlg() {
      return alg;
    }

    public boolean inRange(long size) {
      return size >= start && size < end;
    }
  }
}


四、应用

JDK的 Arrays 的Comparator就使用了策略模式。


五、作用

(1)体现了“对修改关闭,对扩展开放”原则,客户端增加行为不用修改原有代码,只要添加一种策略(或者行为)即可,避免了使用多重转移语句(if..else if..else)

(2)提供了可以替换继承关系的办法: 策略模式将算法封装在独立的Strategy类中使得你可以独立于其Context改变它,使它易于切换、易于理解、易于扩展

(3)需要注意的是:每添加一个策略就要增加一个类,当策略过多是会导致类数目庞大

关注私信可获取更多详细课程资料

展开阅读全文

页面更新:2024-03-30

标签:策略   模式   逗号   分支   算法   语句   客户端   接口   定义   大小   代码   文件

1 2 3 4 5

上滑加载更多 ↓
推荐阅读:
友情链接:
更多:

本站资料均由网友自行发布提供,仅用于学习交流。如有版权问题,请与我联系,QQ:4156828  

© CopyRight 2008-2024 All Rights Reserved. Powered By bs178.com 闽ICP备11008920号-3
闽公网安备35020302034844号

Top