今天,看java编程思想9.3章学习到了策略模式,以前也学习过,总是忘,所以记录一下。
首先需要说明的是,设计模式只是编写低耦合,高内聚,扩展性好的一种实现方式,它是人们总结出来的经验,不是规定一定要这么做,但是设计模式都遵循六大原则,这是设计类的时候尽量要去遵守的,这样每个人都可以有自己的设计模式。
策略模式定义什么的就先不说了,直接来个实际问题比较容易理解
假设现在公司想让我开发一个排序算法库,然后公司的其他开发人员(客户端程序员)会调用这些算法,实现一些功能。 排序算法有如下:
1. 冒泡排序
2. 插入排序
3. 快速排序
4. 堆排序
那么我该怎么设计这个库,才能让 其他开发人员容易调用,然后我自己以后也容易再增加算法呢?
先不管了,完成任务了事(为了方便写在一个文件里了)
import java.lang.*;
import java.util.*;
class SortUtils{
public int[] maopaoSort(int[] src){
System.out.println("after maopao");
return src;
}
public int[] charuSort(int[] src){
System.out.println("after charu");
return src;
}
public int[] kuaisuSort(int[] src){
System.out.println("after kuaisu");
return src;
}
public int[] duiSort(int[] src){
System.out.println("after dui");
return src;
}
}
// Main 是客户端程序员需要建的
public class Main{
public static void print(int[] res){
for(int i=0; i<5; i++){
System.out.print(res[i]+" ");
}
System.out.println("-------");
}
public static void main(String[] args){
SortUtils su = new SortUtils();
int[] src = {1,2,3,4,5};
System.out.println("src");
print(src);
int[] res = su.maopaoSort(src);
print(res);
res = su.charuSort(src);
print(res);
res = su.kuaisuSort(src);
print(res);
res = su.duiSort(src);
print(res);
}
}
排序算法有很多种,有的速度比较快,有的占用的内存小,有的排序比较稳定,其他的开发人员可以自由的选择他想要的排序算法,上面的代码看起来可以正常的工作了(假装的),客户端程序要只需要调用su.xxxSort(int [] src),就可以使用了。但是如果我们想要增加一个排序算法比如基数排序,那就需要在这个文件中添加一个方法jishuSort(int[] src),这样就违反了开闭原则,即对修改关闭,对扩展开放。意思就是说如果随便修改原有的类的话容易引入错误,导致原有的功能出现问题,所以尽量去增加新的类去完成功能。所以我们可以把这些排序算法都设计成单独的类,而且这些类都具有相似的功能,我们可以设计一个抽象的父类,让具体的排序算法都继承父类去实现。然后用int[]也不好,相信客户端程序员一般都会用List<Integer>
去保存原始数组,最后,新一代的代码出炉了。
import java.lang.*;
import java.util.*;
abstract class Sort{
abstract public List<Integer> sort(List<Integer> src);
}
class MaopaoSort extends Sort{
public List<Integer> sort(List<Integer> src){
System.out.println("after maopao");
return src;
}
}
class CharuSort extends Sort{
public List<Integer> sort(List<Integer> src){
System.out.println("after charu");
return src;
}
}
class KuaisuSort extends Sort{
public List<Integer> sort(List<Integer> src){
System.out.println("after kuaisu");
return src;
}
}
class DuiSort extends Sort{
public List<Integer> sort(List<Integer> src){
System.out.println("after dui");
return src;
}
}
public class Main{
public static void print(List<Integer> res){
for(int i=0; i<5; i++){
System.out.print(res.get(i)+" ");
}
System.out.println("-------");
}
public static void main(String[] args){
List<Integer> src = new ArrayList<Integer>();
src.add(1); src.add(2); src.add(3); src.add(4); src.add(5);
Sort s = new MaopaoSort();
List<Integer> res = s.sort(src);
print(res);
s = new CharuSort();
res = s.sort(src);
print(res);
s = new KuaisuSort();
res = s.sort(src);
print(res);
s = new DuiSort();
res = s.sort(src);
print(res);
}
}
这样如果在增加一个基数排序的话,只需要编写一个继承Sort的类并实现sort方法就可以了。嗯。。还有一个地方需要完善一下,客户端程序员调用具体的排序算法时需要知道具体的方法sort,可不可以把这个sort隐藏一下,这样改名字什么的,客户端程序员就不需要变代码啦。那么再增加一个类,帮助客户端程序员去调用sort方法。可以这样写
import java.lang.*;
import java.util.*;
abstract class Sort{
abstract public List<Integer> sort(List<Integer> src);
}
class MaopaoSort extends Sort{
public List<Integer> sort(List<Integer> src){
System.out.println("after maopao");
return src;
}
}
class CharuSort extends Sort{
public List<Integer> sort(List<Integer> src){
System.out.println("after charu");
return src;
}
}
class KuaisuSort extends Sort{
public List<Integer> sort(List<Integer> src){
System.out.println("after kuaisu");
return src;
}
}
class DuiSort extends Sort{
public List<Integer> sort(List<Integer> src){
System.out.println("after dui");
return src;
}
}
// 增加的
class Apply {
private static void print(List<Integer> res){
for(int i=0; i<5; i++){
System.out.print(res.get(i)+" ");
}
System.out.println("-------");
}
public static List<Integer> sort(Sort s,List<Integer> src){
List<Integer> res = s.sort(src);
print(res);
return res;
}
}
public class Main{
public static void main(String[] args){
List<Integer> src = new ArrayList<Integer>();
src.add(1); src.add(2); src.add(3); src.add(4); src.add(5);
Apply.sort(new MaopaoSort(), src);
Apply.sort(new CharuSort(), src);
Apply.sort(new KuaisuSort(), src);
Apply.sort(new DuiSort(), src);
}
}
增加了Apply类,使用process就可以来完成排序算法啦,客户端程序调用起来就不需要知道排序算法内部是通过sort函数来实现的了,调用起来也很简单,并且可以在Apply中添加一些别的功能,比如这里把打印函数放在里面了,而且内部怎么变化,客户端程序员都不要去知道。
回头来看看 策略模式的定义
策略模式:定义一系列的算法,把每一个算法封装起来, 并且使它们可相互替换。本模式使得算法可独立于使用它的客户而变化。
图解:
这样就比较容易理解了。