[design pattern](1) Strategy
引言
最近,在学习设计模式相关的知识。本博客主要想讲一讲策略模式,这也是我学习的第一个模式。写下这篇博客,主要想记录下个人的一点理解,也是想通过写博客的方式来加深对与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
- 定义: 定义一系列的算法,将每一个算法封装起来,并且让这些封装的算法之间可以相互替换。该模式可以使算法独立于使用它们的客户而变化。
- 类图:

通过上面的类图我们可以总结出一下几点:
- 具体算法类 ConcreteStrategyA 和 ConcreteStrategyA 都继承了 Strategy 接口,并且都实现了 algorithm 方法。通过实现接口我们可以很好的实践 开闭原则 ,我们也可以很好的实现扩展
- 类 Client 中有一个 Strategy 变量,通过设置这个变量我们可以很容易的转换我们的算法
- 实现步骤:
- 首先定义一个接口
- 让所有的算法都实现这个接口
- 让客户端持有这个接口
重构思考题
那么通过对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的更多相关文章
- Design Pattern - Strategy
Strategy Pattern: The Strategy Pattern defines a family of algorithms,encapsulates each one,and ...
- 说说设计模式~大话目录(Design Pattern)
回到占占推荐博客索引 设计模式(Design pattern)与其它知识不同,它没有华丽的外表,没有吸引人的工具去实现,它是一种心法,一种内功,如果你希望在软件开发领域有一种新的突破,一个质的飞越,那 ...
- 设计模式(Design Pattern)系列之.NET专题
最近,不是特别忙,重新翻了下设计模式,特地在此记录一下.会不定期更新本系列专题文章. 设计模式(Design pattern)是一套被反复使用.多数人知晓的.经过分类编目的.代码设计经验的总结. 使用 ...
- [转]Design Pattern Interview Questions - Part 3
State, Stratergy, Visitor Adapter and fly weight design pattern from interview perspective. (I) Can ...
- [转]Design Pattern Interview Questions - Part 1
Factory, Abstract factory, prototype pattern (B) What are design patterns? (A) Can you explain facto ...
- 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 ...
- 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 ...
- java设计模式大全 Design pattern samples in Java(最经典最全的资料)
java设计模式大全 Design pattern samples in Java(最经典最全的资料) 2015年06月19日 13:10:58 阅读数:11100 Design pattern sa ...
- [转]Design Pattern Interview Questions - Part 4
Bridge Pattern, Composite Pattern, Decorator Pattern, Facade Pattern, COR Pattern, Proxy Pattern, te ...
随机推荐
- 11g Oracle Rac安装(基于linux6)
安装 Oracle 11gR2 RAC on Linux 6 本文介绍如何在Oracle Linux 6上安装2节点Oracle 11gR2 Real Application Cluster(RAC) ...
- P1074 靶形数独 dfs+预处理
https://www.luogu.org/problemnew/show/P1074 显然是dfs 而且没有什么剪枝记忆化之类的 但是预处理比较麻烦 我用三个二维数组存状态:visx[x][i]代表 ...
- SQL Server中的扩展事件学习系列
SQL Server 扩展事件(Extented Events)从入门到进阶(1)——从SQL Trace到Extented Events SQL Server 扩展事件(Extented Event ...
- 将从model中获得的数据传到js函数中
刚遇到了一种情况,从controller中获得的model是一个集合,需要将这个集合循环放到标签中,并且需要为这些标签添加点击事件,每个值传入对应的点击事件函数中,由于model中的值是通过${ite ...
- 本地项目代码上传至github
初始化本地目录:git init cd到个人本地项目代码文件目录下,执行git init命令 添加项目文件到本地仓库:git add . git commit -m "提交说明" ...
- java 异常体系详细介绍
一.异常概述与异常体系结构 异常:在Java语言中,将程序执行中发生的不正常情况称为"异常".(开发过程中的语法错误和逻辑错误不是异常). Java把异常当作对象来处理,并定义一个 ...
- 利用中转输出表制作HijackDll
[原创]利用中转输出表制作HijackDll(附工具源码)作 者: baixinye时 间: 2012-08-05,16:48:45链 接: http://bbs.pediy.com/showthre ...
- 2019 上海市大学生网络安全大赛 RE部分WP
这次比赛就做了这一道逆向题,看到队友的WP,下面的对v10的加密方式为RC4,从我提取的v4数组就能够察觉出这是CR4了,自己傻乎乎的用OD调试,跟踪数据半天才做出来,还是见得的少了... ...下面 ...
- jekins部署
以下以在MAC上安装为例: 1.从官网下载安装包 https://jenkins.io/download 2.双击pkg包安装程序开始安装.(这种方式安装的不好卸载) 提示输入密码,按照提示的路径找到 ...
- es6 generator函数的异步编程
es6 generator函数,我们都知道asycn和await是generator函数的语法糖,那么genertaor怎么样才能实现asycn和await的功能呢? 1.thunk函数 将函数 ...