所有源碼的git地址https://gitee.com/0x208_jackson/design-patterns
1、設(shè)計(jì)模式該怎么用
當(dāng)我們項(xiàng)目中出現(xiàn)了多個(gè)if……else的時(shí)候就可以選擇使用策略模式,策略模式就是做同一件事件的不同的方法,設(shè)計(jì)模式說(shuō)到底就是java多態(tài)的靈活運(yùn)用。設(shè)計(jì)項(xiàng)目時(shí)我們一般要遵循開(kāi)閉原則,即關(guān)閉修改,打開(kāi)擴(kuò)展,也就是說(shuō)盡量別去修改現(xiàn)有的代碼,而是對(duì)其進(jìn)行擴(kuò)展,這就要求我們?cè)谠O(shè)計(jì)的時(shí)候需要考慮到可以進(jìn)行靈活的擴(kuò)展。
2、策略模式-比較動(dòng)物大小
2.1、根據(jù)體重比較
我們現(xiàn)在有一只貓,根據(jù)體重比較貓的大小,代碼如下:
貓的實(shí)體對(duì)象
package com.xin.demo.strategy;
import java.io.Serializable;
public class Cat implements Serializable {
private final int weight;
private final int height;
public int compareToHeight(Cat cat) {
return this.weight - cat.weight;
}
public Cat(int weight, int height) {
this.weight = weight;
this.height = height;
}
@Override
public String toString() {
return "Cat{" +
"weight=" + weight +
", height=" + height +
'}';
}
}
排序:
package com.xin.demo.strategy;
public class Sort {
// 此處通過(guò) 采用選擇排序進(jìn)行排序
public static void selectionSort(Cat[] arr) {
if (arr == null || arr.length < 2) {
return;
}
for (int i = 0; i < arr.length - 1; i++) {
int minIndex = i;
for (int j = i + 1; j < arr.length; j++) {
// 此處是重點(diǎn)需要注意,注意看調(diào)用的方法名
// 此處需要根據(jù) 不同的比較方式去調(diào)用不同的方法,也就是會(huì)產(chǎn)生多個(gè)if……else
minIndex = arr[j].compareToHeight(arr[minIndex]) < 0 ? j : minIndex;
}
swap(arr, i, minIndex);
}
}
public static void swap(Cat[] arr, int i, int j) {
Cat tmp = arr[i];
arr[i] = arr[j];
arr[j] = tmp;
}
}
執(zhí)行:
package com.xin.demo.strategy;
import java.util.Arrays;
public class OperatorMain {
public static void main(String[] args) {
Cat[] a = {new Cat(23, 2),
new Cat(14, 11),
new Cat(5, 7),
new Cat(1, 1)};
Sort.selectionSort(a);
System.out.println(Arrays.toString(a));
}
}
2.2、根據(jù)身高比較
現(xiàn)在我希望根據(jù)貓的身高比較貓的大小,按照常規(guī)寫(xiě)法,我們需要<font color='red'>在 Cat </font>對(duì)象里面在實(shí)現(xiàn)一個(gè)方法.
package com.xin.demo.strategy;
import java.io.Serializable;
public class Cat implements Serializable {
private final int weight;
private final int height;
public int compareToHeight(Cat cat) {
return this.weight - cat.weight;
}
// 此處為新增加的 根據(jù)體重進(jìn)行比較的方法
public int compareToWeight(Cat cat) {
return this.weight - cat.weight;
}
public Cat(int weight, int height) {
this.weight = weight;
this.height = height;
}
@Override
public String toString() {
return "Cat{" +
"weight=" + weight +
", height=" + height +
'}';
}
}
修改排序的調(diào)用方法
package com.xin.demo.strategy;
public class Sort {
// 此處通過(guò) 采用選擇排序進(jìn)行排序
public static void selectionSort(Cat[] arr) {
if (arr == null || arr.length < 2) {
return;
}
for (int i = 0; i < arr.length - 1; i++) {
int minIndex = i;
for (int j = i + 1; j < arr.length; j++) {
// 注意此處改成了 調(diào)用體重的方法
// 此處需要根據(jù) 不同的比較方式去調(diào)用不同的方法,也就是會(huì)產(chǎn)生多個(gè)if……else
minIndex = arr[j].compareToWeight(arr[minIndex]) < 0 ? j : minIndex;
}
swap(arr, i, minIndex);
}
}
public static void swap(Cat[] arr, int i, int j) {
Cat tmp = arr[i];
arr[i] = arr[j];
arr[j] = tmp;
}
}
2.3、根據(jù)策略模式
以上兩種情況我們發(fā)現(xiàn),如果在做同一件貓的大小的比較,根據(jù)不同的方式去做的時(shí)候我們需要寫(xiě)很多冗余的代碼,且不利于擴(kuò)展,如在增加一種比較方式的時(shí)候,我們需要繼續(xù)進(jìn)行方法的迭代,且排序方法需要在增加或者重寫(xiě),此處策略主要針對(duì)的是排序部分。
既然是同一件事情,不同的方式去做,那么我們可以定義一個(gè)比較器接口,通過(guò)不同的實(shí)現(xiàn)來(lái)完成。
首先定義一個(gè)接口:
package com.xin.demo.strategy;
public interface Comparator<T> {
// 比較器
int compare(T o1, T o2);
}
對(duì)應(yīng)的實(shí)現(xiàn):
體重:
package com.xin.demo.strategy;
public class CatCompareToHeight implements Comparator<Cat> {
@Override
public int compare(Cat o1, Cat o2) {
return o1.height - o2.height;
}
}
身高:
package com.xin.demo.strategy;
public class CatCompareToWeight implements Comparator<Cat> {
@Override
public int compare(Cat o1, Cat o2) {
return o1.weight - o2.weight;
}
}
排序方法:
package com.xin.demo.strategy;
public class StrategySort<T> {
// 此處通過(guò) 采用選擇排序進(jìn)行排序
public void selectionSort(T[] arr, Comparator<T> comparator) {
if (arr == null || arr.length < 2) {
return;
}
for (int i = 0; i < arr.length - 1; i++) {
int minIndex = i;
for (int j = i + 1; j < arr.length; j++) {
// 重點(diǎn)
minIndex = comparator.compare(arr[j], arr[minIndex]) < 0 ? j : minIndex;
}
swap(arr, i, minIndex);
}
}
public void swap(T[] arr, int i, int j) {
T tmp = arr[i];
arr[i] = arr[j];
arr[j] = tmp;
}
}
執(zhí)行:
package com.xin.demo.strategy;
import java.util.Arrays;
public class OperatorMain {
public static void main(String[] args) {
Cat[] cat = {new Cat(3, 4),
new Cat(14, 11),
new Cat(5, 17),
new Cat(1, 2)};
// 普通寫(xiě)法
Sort.selectionSort(cat);
System.out.println(Arrays.toString(cat));
// 策略模式寫(xiě)法
StrategySort<Cat> strategySort = new StrategySort<>();
// 傳進(jìn)去需要比較的對(duì)象,以及對(duì)應(yīng)的策略,也就是對(duì)應(yīng)的比較方式
// 根據(jù)身高比較
strategySort.selectionSort(cat, new CatCompareToHeight());
System.out.println("根據(jù)height排序:"+Arrays.toString(cat));
//根據(jù)體重進(jìn)行比較
strategySort.selectionSort(cat, new CatCompareToWeight());
System.out.println("根據(jù)weight排序:"+Arrays.toString(cat));
}
}
2.4、可以比較任何動(dòng)物的大小
package com.xin.demo.strategy;
import java.util.Arrays;
public class OperatorMain {
public static void main(String[] args) {
// 現(xiàn)在我們不僅可以比較貓的大小,還可以比較任何一個(gè)動(dòng)物的大小
// lambda 表達(dá)式寫(xiě)法
StrategySort<Dog> dogStrategySort = new StrategySort<>();
Dog[] dogs = {new Dog(3, 9),
new Dog(1, 11),
new Dog(4, 1),
new Dog(2, 2)};
dogStrategySort.selectionSort(dogs, new Comparator<Dog>() {
@Override
public int compare(Dog o1, Dog o2) {
return o1.height - o2.height;
}
});
System.out.println(Arrays.toString(dogs));
}
}