引言

最近,在学习设计模式相关的知识。本博客主要想讲一讲策略模式,这也是我学习的第一个模式。写下这篇博客,主要想记录下个人的一点理解,也是想通过写博客的方式来加深对与Strategy的一点理解。以下的内容如果有什么说的不对的地方,还请各位大神指正。

思考题

首先我们来思考下面的一个问题:

问题:写出冒泡排序和快速排序算法,并且根据传参不同,使用不同的排序算法排序。

首先,来看没有使用设计模式的代码是什么样子:

SortAlgorithm.java:
import java.util.Random;
import java.util.Arrays; public class SortAlgorithm {
private static int index = 10000;
private static int randomMax = 50000;
private static Integer[] oldOrder = new Integer[index];
private static Random random = new Random();
static {
for(int i = 0; i < index; i++) {
oldOrder[i] = random.nextInt(randomMax);
}
} //通过设置算法名称来决定用什么算法
private String algorithmName; public static void main(String... args) {
SortAlgorithm sortAlgorithm = new SortAlgorithm();
Integer[] oldOrder1 = Arrays.copyOf(oldOrder, index);
Integer[] oldOrder2 = Arrays.copyOf(oldOrder, index); sortAlgorithm.setAlgorithmName("bubble");
//System.out.println(String.format("BubbleSort sort before order:%s", Arrays.asList(oldOrder1).toString()));
long startTime = System.currentTimeMillis();
Integer[] newOrder1 = sortAlgorithm.executeAlgorithm(oldOrder1);
System.out.println(String.format("BubbleSort take time:%s", System.currentTimeMillis() - startTime));
//System.out.println(String.format("BubbleSort sort after order:%s", Arrays.asList(newOrder1).toString())); sortAlgorithm.setAlgorithmName("quick");
//System.out.println(String.format("QuickSort sort before order:%s", Arrays.asList(oldOrder2).toString()));
startTime = System.currentTimeMillis();
Integer[] newOrder2 = sortAlgorithm.executeAlgorithm(oldOrder2);
System.out.println(String.format("QuickSort take time:%s", System.currentTimeMillis() - startTime));
//System.out.println(String.format("QuickSort sort after order:%s", Arrays.asList(newOrder2).toString()));
} public Integer[] executeAlgorithm(Integer[] oldOrder) {
if("bubble".equals(algorithmName)){
return sortBubble(oldOrder);
}else if("quick".equals(algorithmName)) {
return sortQuick(oldOrder);
}
return null;
} public void setAlgorithmName(String algorithmName) {
this.algorithmName = algorithmName;
} private Integer[] sortBubble(Integer[] oldOrder) {
for(int i = 1; i < oldOrder.length; i++) {
for(int j = 0; j < oldOrder.length - i; j++) {
if(oldOrder[j] > oldOrder[j + 1]) {
Integer temp = oldOrder[j];
oldOrder[j] = oldOrder[j + 1];
oldOrder[j + 1] = temp;
}
}
}
return oldOrder;
} private Integer[] sortQuick(Integer[] oldOrder) {
partSort(oldOrder, 0, oldOrder.length - 1);
return oldOrder;
} private void partSort(Integer[] oldOrder, int start, int end) {
if(start < end) {
int middle = swaps(oldOrder, start, end);
partSort(oldOrder, start, middle);
partSort(oldOrder, middle + 1, end);
}
} private int swaps(Integer[] oldOrder, int start, int end) {
Integer temp = oldOrder[start];
for(;start < end;) {
for(;start < end && temp <= oldOrder[end]; end--);
if(start < end) {
oldOrder[start] = oldOrder[end];
start++;
}
for(;start < end && temp > oldOrder[start]; start++);
if(start < end) {
oldOrder[end] = oldOrder[start];
end--;
}
}
oldOrder[start] = temp;
return start;
}
}

print:

BubbleSort take time:717
QuickSort take time:14

上面是我的实现,所有的代码都集中在SortAlgorithm一个class里面。那么试想一下这时候如果我们想再增加一个选择排序,那么我们需要修改SortAlgorithm类,这样我们就违背了 开闭原则 。因此我们要想办法把修改变为增加。那么怎么样才能将修改变为增加呢?通过使用 strategy 可以做到。

介绍strategy

  • 定义: 定义一系列的算法,将每一个算法封装起来,并且让这些封装的算法之间可以相互替换。该模式可以使算法独立于使用它们的客户而变化。
  • 类图:

通过上面的类图我们可以总结出一下几点:

  1. 具体算法类 ConcreteStrategyA 和 ConcreteStrategyA 都继承了 Strategy 接口,并且都实现了 algorithm 方法。通过实现接口我们可以很好的实践 开闭原则 ,我们也可以很好的实现扩展
  2. 类 Client 中有一个 Strategy 变量,通过设置这个变量我们可以很容易的转换我们的算法
  • 实现步骤:
  1. 首先定义一个接口
  2. 让所有的算法都实现这个接口
  3. 让客户端持有这个接口

重构思考题

那么通过对Strategy的学习,我们来重构下我们上面的问题:

首先,我们定义一个接口:

Sort.java:

public interface Sort {
Integer[] sort(Integer[] oldOrder);
}

然后,我们定义一系列的算法实现上面定义的接口:

BubbleSort.java:

public class BubbleSort implements Sort {
@Override
public Integer[] sort(Integer[] oldOrder) {
for(int i = 1; i < oldOrder.length; i++) {
for(int j = 0; j < oldOrder.length - i; j++) {
if(oldOrder[j] > oldOrder[j + 1]) {
Integer temp = oldOrder[j];
oldOrder[j] = oldOrder[j + 1];
oldOrder[j + 1] = temp;
}
}
}
return oldOrder;
}
}

QuickSort.java:

public class QuickSort implements Sort {
@Override
public Integer[] sort(Integer[] oldOrder) {
partSort(oldOrder, 0, oldOrder.length - 1);
return oldOrder;
} private void partSort(Integer[] oldOrder, int start, int end) {
if(start < end) {
int middle = swaps(oldOrder, start, end);
partSort(oldOrder, start, middle);
partSort(oldOrder, middle + 1, end);
}
} private int swaps(Integer[] oldOrder, int start, int end) {
Integer temp = oldOrder[start];
for(;start < end;) {
for(;start < end && temp <= oldOrder[end]; end--);
if(start < end) {
oldOrder[start] = oldOrder[end];
start++;
}
for(;start < end && temp > oldOrder[start]; start++);
if(start < end) {
oldOrder[end] = oldOrder[start];
end--;
}
}
oldOrder[start] = temp;
return start;
}
}

最后,我们实现一个算法调用类:

SortAlgorithm.java:

public class SortAlgorithm {
private Sort sort; public void setSort(Sort sort) {
this.sort = sort;
} public Integer[] executeAlgorithm(Integer[] oldOrder) {
return sort.sort(oldOrder);
}
}

测试用例:

Client.java:

import java.util.Random;
import java.util.Arrays; public class Client {
private static int index = 10;
private static int randomMax = 100;
private static Integer[] oldOrder = new Integer[index];
private static Random random = new Random();
static {
for(int i = 0; i < index; i++) {
oldOrder[i] = random.nextInt(randomMax);
}
} public static void main(String... args) {
SortAlgorithm sortAlgorithm = new SortAlgorithm();
Integer[] oldOrder1 = Arrays.copyOf(oldOrder, index);
Integer[] oldOrder2 = Arrays.copyOf(oldOrder, index); sortAlgorithm.setSort(new BubbleSort());
System.out.println(String.format("BubbleSort sort before order:%s", Arrays.asList(oldOrder1).toString()));
long startTime = System.currentTimeMillis();
Integer[] newOrder1 = sortAlgorithm.executeAlgorithm(oldOrder1);
System.out.println(String.format("BubbleSort take time:%s", System.currentTimeMillis() - startTime));
System.out.println(String.format("BubbleSort sort after order:%s", Arrays.asList(newOrder1).toString())); sortAlgorithm.setSort(new QuickSort());
System.out.println(String.format("QuickSort sort before order:%s", Arrays.asList(oldOrder2).toString()));
startTime = System.currentTimeMillis();
Integer[] newOrder2 = sortAlgorithm.executeAlgorithm(oldOrder2);
System.out.println(String.format("QuickSort take time:%s", System.currentTimeMillis() - startTime));
System.out.println(String.format("QuickSort sort after order:%s", Arrays.asList(newOrder2).toString()));
} private static int[] copyOldOrder(int[] oldOrder) {
int[] result = new int[index];
for(int i = 0; i < index; i++) {
result[i] = oldOrder[i];
}
return result;
}
}

上面的代码使用了策略模式,通过使用这个模式我们可以很容易的扩展,现在只要我们实现 Sort 接口就可以扩展我们的排序算法。

[design pattern](1) Strategy的更多相关文章

  1. Design Pattern - Strategy

    Strategy Pattern:     The Strategy Pattern defines a family of algorithms,encapsulates each one,and ...

  2. 说说设计模式~大话目录(Design Pattern)

    回到占占推荐博客索引 设计模式(Design pattern)与其它知识不同,它没有华丽的外表,没有吸引人的工具去实现,它是一种心法,一种内功,如果你希望在软件开发领域有一种新的突破,一个质的飞越,那 ...

  3. 设计模式(Design Pattern)系列之.NET专题

    最近,不是特别忙,重新翻了下设计模式,特地在此记录一下.会不定期更新本系列专题文章. 设计模式(Design pattern)是一套被反复使用.多数人知晓的.经过分类编目的.代码设计经验的总结. 使用 ...

  4. [转]Design Pattern Interview Questions - Part 3

    State, Stratergy, Visitor Adapter and fly weight design pattern from interview perspective. (I) Can ...

  5. [转]Design Pattern Interview Questions - Part 1

    Factory, Abstract factory, prototype pattern (B) What are design patterns? (A) Can you explain facto ...

  6. C++ Design Pattern: What is a Design Pattern?

    Q: What is a Design Pattern? A: Design Patterns represent solutions to problems what arise when deve ...

  7. Design Pattern in Simple Examples

    Instead of defining what is design pattern lets define what we mean by design and what we mean by pa ...

  8. java设计模式大全 Design pattern samples in Java(最经典最全的资料)

    java设计模式大全 Design pattern samples in Java(最经典最全的资料) 2015年06月19日 13:10:58 阅读数:11100 Design pattern sa ...

  9. [转]Design Pattern Interview Questions - Part 4

    Bridge Pattern, Composite Pattern, Decorator Pattern, Facade Pattern, COR Pattern, Proxy Pattern, te ...

随机推荐

  1. OSPF与ACL 综合应用

    1.企业内网运行OSPF路由协议,区域规划如图所示:2.财务和研发所在的区域不受其他区域链路不稳定性影响:3.R1.R2.R3只允许被IT登录管理:4.YF和CW之间不能互通,但都可以与IT互通:5. ...

  2. java基础笔记(2)

    java中成员变量是有默认初始值的,而局部变量是没有的: 构造方法名和类名相同,没有返回值,即结构如下:public 构造方法名(): 实例化类的本质就是调用了类的构造方法: 如果自定义了构造方法,就 ...

  3. 数位DP 计划

    通常的数位dp可以写成如下形式: [cpp] view plain copy int dfs(int i, int s, bool e) { if (i==-1) return s==target_s ...

  4. NOIP赛前集训备忘录(含每日总结)(日更?。。。)

    NOIP赛前集训备忘录(含每日考试总结) 标签: 有用的东西~(≧▽≦)/~啦啦啦 阅读体验:https://zybuluo.com/Junlier/note/1279194 考试每日总结(这个东西是 ...

  5. swtich和case语句中,定义变量要加花括号

    转自: http://blog.chinaunix.net/uid-27103408-id-3340702.html http://www.xuebuyuan.com/2070170.html swi ...

  6. Spark出现java.lang.stackoverflowerror的解决方法

    正在测试的程序需要多次迭代(400+次),每次迭代有复杂的运算 迭代到100多次的时候报java.lang.stackoverflowerror的错误 解决方法:先checkpoint()再count ...

  7. Django之F和Q查询

    一.F查询 rom django.db.models import F from app01.models import Book Book.objects.update(price=F(" ...

  8. getchar、putchar、puts、gets

    getchar(字符)  输入获取一个字符 putchar(字符)  输出控制台一个字符 scanf()格式化输入 printf() 格式化输出 gets(arr) 输入一个字符串给已经声明的数组ar ...

  9. Vue框架前言

    Vue框架 Vue 框架: 官网 vue框架:渐进式JavaScript框架 vue一个环境:可以只控制页面中一个标签.可以控制一组标签.可以控制整个页面.可以控制整个项目 vue可以根据实际需求,选 ...

  10. 关于原型链,原来这么简单?—————终结__proto__和prototype的那些事

    今天,一个技术群里小朋友提出一个问题: Object.prototype.a = function () { console.log('a') } Function.prototype.b = fun ...