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

策略模式:


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


常用七种:
冒泡排序
选择排序
插入排序
希尔排序
快速排序
归并排序
堆排序
 
用一个排序的实例来解释策略模式:
/**
 * 用数组排序抽出策略模式
 * @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);
//当然也可以使用内部类,大家自己去实现以下吧

}
}






说了这么多,其实比较器就是使用了策略模式。
也就是说,我要排序的时候,我只要定一个策略就可以了。不同的策略就会有不同的结果。







评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值