您的位置:首页 > 编程语言 > Java开发

Java23种设计模式:策略模式(四)

2017-03-03 17:32 337 查看
策略模式:

用一个排序来说一下策略模式:

常用七种:

冒泡排序

选择排序

插入排序

希尔排序

快速排序

归并排序

堆排序

用一个排序的实例来解释策略模式:

/**

* 用数组排序抽出策略模式

* @author 向平

*

*/

public class XPSortedUtil {

/**

* 排序int类型的

*/

public static void sort(int[] arr){

for (int i = 0; i < arr.length; i++) {

for (int j = 0; j < arr.length-1; j++) {

if (arr[j] > arr[j+1]) {

swap(arr,j,j+1);

}

}

}

XPPrint(arr);

}

private static void swap(int[] arr,int i, int j) {

int temp = arr[i];

arr[i] = arr[i+1];

arr[i+1] = temp;

}

public static void XPPrint(int[] arr) {

for (int i = 0; i < arr.length; i++) {

System.out.println(arr[i]);

}

}

}

以上是写了一个int数组的排序。如果要一个double类型的排序,那么我们必须要新增一个double数组排序的方法。

double的排序省略了。。。。

如果要写Car类数组的排序,那我们就是写一个Car数组的排序。

/**

* 用数组排序抽出策略模式

* @author 向平

*

*/

public class XPSortedUtil {

/**

* 排序Car类型的

*/

public static void sort(Car[] arr){

for (int i = 0; i < arr.length; i++) {

for (int j = 0; j < arr.length-1; j++) {

if (arr[j] > arr[j+1]) {

swap(arr,j,j+1);

}

}

}

XPPrint(arr);

}

private static void swap(Car[] arr,int i, int j) {

Car temp = arr[i];

arr[i] = arr[i+1];

arr[i+1] = temp;

}

}

看到这里大家都发现了,这样写下去不得了。。。。。

这样的话有多少类,那就有多少排序方法,那你写的这个排序工具类,简直就没法去维护和兼容

这样的情况我们该怎么办呢????

我们能不能订一套排序的统一规则呢?

当然可以,既然说到了定制统一规则,那我们一下子就会想到接口,没错,就是接口。

好,既然我们想到用接口来定义一个统一排序的规则,那我们就定义个XPComparable接口把:接口中有一个compareTo方法

************重点来了***************

XPComparable定义好了以后,叫要进行排序的类实现它。然后根据不同类排序的规则,随意自定义规则。

然后在排序工具类中调用的时候,用XPComparable的引用去实现多态。用XPComparable的引用去调用compareTo方法,

传入的是什么类的类型数组,就会调用该类中自定义实现的compareTo方法进行比较。

比如:汽车类实现了XPComparable接口,那汽车就可以比较大小了

public class Car implements XPComparable{

private String type;

private int money;

public Car() {

super();

}

public Car(String type, int money) {

super();

this.type = type;

this.money = money;

}

public String getType() {

return type;

}

public void setType(String type) {

this.type = type;

}

public int getMoney() {

return money;

}

public void setMoney(int money) {

this.money = money;

}

@Override

public int compareTo(Object obj) throws Exception {

if (obj instanceof Car) {

Car objCar = (Car) obj;

if (this.getMoney() > objCar.getMoney()) {

return 1;

}else if (this.getMoney()==objCar.getMoney()) {

return 0;

}else{

return -1;

}

}else{

//如果传入的不是Car类说明这个不能进行对比,所以抛异常

throw new Exception();

}

}

}

排序工具类也需要变动一下:

public class XPSortedUtil {

/**

* 排序int类型的

*/

public static void sort(int[] arr){

for (int i = 0; i < arr.length; i++) {

for (int j = 0; j < arr.length-1; j++) {

if (arr[j] > arr[j+1]) {

swap(arr,j,j+1);

}

}

}

XPPrint(arr);

}

private static void swap(int[] arr,int i, int j) {

int temp = arr[i];

arr[i] = arr[i+1];

arr[i+1] = temp;

}

public static void XPPrint(int[] arr) {

for (int i = 0; i < arr.length; i++) {

System.out.println(arr[i]);

}

}

/**

* 这个就是满足所有类型的排序,只要这个类实现了XPComparable接口,也就是说只要自定义类遵循了排序规则,就可以排序

* @param arr

*/

public static void sort(Object[] arr){

for (int i = 0; i < arr.length; i++) {

for (int j = 0; j < arr.length-1; j++) {

//关键部分,多态:用父接口指向子类对象

XPComparable obj1 = (XPComparable) arr[j];

XPComparable obj2 = (XPComparable) arr[j+1];

//等于1:obj1>obj2 等于0:obj1=obj2 等于-1:obj1<obj2

//有可能类型不匹配,所以异常处理一下

try {

if (obj1.compareTo(obj2)== 1) {

swap(arr,j,j+1);

}

} catch (Exception e) {

e.printStackTrace();

}

}

}

}

private static void swap(Object[] arr, int x, int y) {

Object object = arr[x];

arr[x] = arr[y];

arr[y] = object;

}

}

以上这么多的好处是什么吗?

就是你要怎么排序,就可以在自己类里面定具体规则,我要根据什么方式排序。

比如:我有个学生类,实现了XPComparable接口了,我就可以在compareTo方法中写排序具体的规则了,如果现在我是按照学号排序,

可能下次我的需求变了,你就直接在你的学生类的compareTo方法中修改排序规则即可,不会对其他的有任何影响。

大家慢慢体会一下这种设计的好处。

小结一下:说了这么多有提到了多态,没错多态才是面向对象的核心,多态是你系统或项目后期扩展和维护的重要手段之一。

设计模式是什么?

其实就是把简单的东西复杂化,没错是这样。那为嘛要复杂化呢?是为了适应你后期的项目需求,多态是设计模式中一个非常重要的组成部分。但是在使用设计模式时也不要前期设计的过度复杂,适用就可以了

因为你的设计是随项目的增进而调整。不要为了设计而设计喔。。。。

大家别急,还没到策略设计模式。。。万里长城才第一步。。。。

请大家分析一个问题:

上面虽然解决了为统一比较定义规则,然后也是实现了所有类的排序,但是真没有问题吗????

1.虽然把排序规则可以定在所有排序类的内部,根据自己的排序需求来定制。但是如果某一天我想要修改排序的具体规则。那是不是又得去动我们已经写好的代码。

如:假设我现在有个学生类,学生类里有:学号,年龄,学分,体重,身高

1>.那我当前是按照学号写的排序规则,那下次如果我要以年龄来排序,我是不是要动已经写好的代码。

2>.好,我就当你改好了,但是如果有一天又变了,你是不是又要去改规则,那周而复始,你就见鬼了。。。太麻烦了,

3>.为什么会这样呢??? 那是因为你的排序规则和你的学生类之间设计的耦合度太高了。应该解耦。

怎么解耦呢???

2.我们可以把排序的具体排序规则把它从具体类中剥离出去。好,没错就是这个思路。我们剥离出来的东西叫 "比较器" 吧

3.具体排序规则也太多了,也就意味着你的比较器也很多,我们也必须要统一下来,使用多态。不然,你又一个噩梦开始了,如果学生类中有 "学号比较器","年龄比较器","学分比较器","体重比较器","身高比较器"

如果不要父类,其实和你上面没有太大的优化,只是把代码剥离了而已。你还得不断的修改 比较器对象。所以我们为所有的比较器顶一个统一的规则,比较器接口。

4.我们就定义一个比较器接口把:Comparator接口:接口中有:compare(Object o1,Object o2)接口

写一段代码理一下思路:

比较器接口:

/**

* 比较器接口

* @author 向平

*

*/

public interface XPComparator {

//如果相等就返回0,如果object1>object2 就返回1 ,如果object1<object2 就返回-1

int compare(Object object1,Object object2);

}

比较器实现:

/**

* 学生具体按学分比较的比较器

* @author 向平

*

*/

public class StudentScoreComparator implements XPComparator{

@Override

public int compare(Object object1, Object object2) {

Student student1 = (Student)object1;

Student student2 = (Student)object2;

if (student1.getScroce()>student2.getScroce()) {

return 1;

}else if (student1.getScroce()<student2.getScroce()) {

return -1;

}

return 0;

}

}

使用比较器:

package com.xp.strategy;

/**

* 学生类

* @author 向平

*

*/

public class Student implements XPComparable{

private String name;

private int age;

private double scroce;

//比较器

private XPComparator comparator;

public Student() {

super();

}

public Student(String name, int age, double scroce) {

super();

this.name = name;

this.age = age;

this.scroce = scroce;

}

public String getName() {

return name;

}

public void setName(String name) {

this.name = name;

}

public int getAge() {

return age;

}

public void setAge(int age) {

this.age = age;

}

public double getScroce() {

return scroce;

}

public void setScroce(double scroce) {

this.scroce = scroce;

}

public XPComparator getComparator() {

return comparator;

}

public void setComparator(XPComparator comparator) {

this.comparator = comparator;

}

/**

* 开始比较

*/

@Override

public int compareTo(Object obj) throws Exception {

//如果我想要切换到其他比较器,我只要外界传入不同比较器对象即可,里面的东西不用在变化

return getComparator().compare(this, obj);

//当然也可以使用内部类,大家自己去实现以下吧

}

}

说了这么多,其实比较器就是使用了策略模式。

也就是说,我要排序的时候,我只要定一个策略就可以了。不同的策略就会有不同的结果。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: