策略模式

开闭原则:对修改关闭,对扩展开放

一、示例

首先写一个自己的Comparator方法(也可以用java的,这里先自己写)

然后传递函数的时候先传递一个T类型的数组,然后再传递一个比较器,这个比较器用来说明这个类型如何比较(好处是可以是不同类的比较器,也可以是同一类的不同属性的比较器)

首先写一个比较器,这里用了泛型

1
2
3
4
5
package strategy;

public interface Comparator<T> {
int compare(T o1, T o2)
}

然后写个示例类,比如Dog类

1
2
3
4
5
6
7
8
9
10
11
12
13
package strategy;

public class Dog {
int food;
Dog(int a){food = a;}

@Override
public String toString() {
return "Dog{" +
"food=" + food +
'}';
}
}

然后写这个Dog类的比较器,Override比较器里的compare方法,对food的大小进行比较

1
2
3
4
5
6
7
8
public class DogComparator implements Comparator<Dog>{
@Override
public int compare(Dog o1, Dog o2) {
if(o1.food < o2.food) return -1;
else if(o1.food >o2.food) return 1;
else return 0;
}
}

然后是比较函数Sorter

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
package strategy;

public class Sorter<T> {
public void sort(T[] arr, Comparator<T> comparator){
for(int i=0; i<arr.length; i++) {
int minPos = i;

for(int j=i+1;j<arr.length;j++){
minPos = comparator.compare(arr[j],arr[minPos]) == -1 ? j : minPos;
}

swap(arr, i, minPos);
}
}

void swap(T[] arr, int i, int j) {
T temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
}

最后在Main里进行测试

1
2
3
4
5
6
7
8
9
10
11
12
package strategy;

import java.util.Arrays;

public class Main {
public static void main(String[] args) {
Dog[] a = {new Dog(3), new Dog(2), new Dog(1)};
Sorter<Dog> sorter = new Sorter<>();
sorter.sort(a,new DogComparator());
System.out.println(Arrays.toString(a));
}
}

二、考虑如何把策略模式应用到工程里

例子是坦克射子弹,老师给的代码太复杂,我简化了一些:

首先是**FireStrategy** 接口

1
2
3
4
5
package tank;

public interface FireStrategy {
void fire(Tank t);
}

DefaultFireStrategyFourDirFireStrategy 分别是实现了这个接口的具体策略类

1
2
3
4
5
6
7
8
package tank;

public class DefaultFireStrategy implements FireStrategy{
@Override
public void fire(Tank t) {
System.out.println("默认开火方法");
}
}
1
2
3
4
5
6
7
8
package tank;

public class FourDirFireStrategy implements FireStrategy{
@Override
public void fire(Tank t) {
System.out.println("四个方向开火");
}
}

Tank 类则持有一个 FireStrategy 引用,可以在运行时根据需要切换不同的开火策略

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
package tank;

public class Tank {
private FireStrategy fireStrategy;

public Tank() {
// 默认使用默认开火策略
this.fireStrategy = new DefaultFireStrategy();
}

// 设置开火策略
public void setFireStrategy(FireStrategy fireStrategy) {
this.fireStrategy = fireStrategy;
}

// 开火
public void fireOutput() {
fireStrategy.fire(this);
}
}

最后是main方法测试

1
2
3
4
5
6
7
8
9
10
11
12
13
14
package tank;

public class Main {
public static void main(String[] args) {
Tank tank = new Tank();

// 默认开火策略
tank.fireOutput();

// 切换为四个方向开火策略
tank.setFireStrategy(new FourDirFireStrategy());
tank.fireOutput();
}
}