设计模式——策略模式(Strategy)
定义:定义了一组算法,将每个算法都封装起来,并且使它们之间可以互换
例如:对于人这个对象的比较,我们可以根据多种方式进行比较 比如年比较,身高比较。这样我们就可以把身高比较和年龄比较这两个策略各自的实现,然后达到我们需要什么样的策略我们就可以去写自己的策略
应用实例:出行方式:步行 ,自行车,飞机等策略
促销的方式:打折,满减等策略
源码分析
Comparator接口
//用于比较大小策略的接口
public interface Comparator<T> {
int compare(T o1, T o2);
}
// class Arrays
public static <T> void sort(T[] a, Comparator<? super T> c) public static <T> void sort(T[] a, Comparator<? super T> c) {
if (c == null) {
sort(a);
} else {
if (LegacyMergeSort.userRequested)
legacyMergeSort(a, c);
else
TimSort.sort(a, 0, a.length, c, null, 0, 0);
}
}
/*在需要对对象数组进行排序的时候我们可以设计一个排序的策略 写一个排序策略类 实现Comparator<T>接口 重写 int compare(T o1, T o2);方法
*这种方式可以根据我们的需要去随时的修改我们的策略,在不同的地方我们可以使用不同的策略(根据我们的需要)
*/
比较
Comparable接口
public interface Comparable<T> {
public int compareTo(T o);
}
//在排序的的时候我们也可以 让我们的类去实现Comparable<T>接口 然后重写 int compareTo(T o); 方法
//但是这样的方式有一点不好,那就是对于这个类 排序的策略是写死的。我们需要修改排序策略的时候我就需要去修改 重写的compareTo方法的内容
对象排序的设计模式实现
public class Strategy01 {
/**
* Person 类 有年龄和身高的属性
*/
static class Person {
private int age;
private int height;
public Person(int age, int height) {
this.age = age;
this.height = height;
}
public int getAge() {
return age;
}
public int getHeight() {
return height;
}
@Override
public String toString() {
return "Person{" +
"age=" + age +
", height=" + height +
'}';
}
}
/**
* 根据年龄进行排序的策略
*/
static class AgeSortStrategy implements Comparator<Person> {
@Override
public int compare(Person o1, Person o2) {
if (o1.age > o2.age) {
return 1;
} else if (o1.age == o2.age) {
return 0;
} else {
return -1;
}
}
}
/**
* 根据身高进行排序的策略
*/
static class HeightSortStrategy implements Comparator<Person> {
@Override
public int compare(Person o1, Person o2) {
if (o1.height > o2.height) {
return 1;
} else if (o1.height == o2.height) {
return 0;
} else {
return -1;
}
}
}
public static void main(String[] args) {
//创建一个三个实例的数组
Person[] peopleList = new Person[]{new Person(30, 130), new Person(20, 190), new Person(25, 110)};
System.out.println("根据年龄排序:");
//使用public static <T> void sort(T[] a, Comparator<? super T> c) 方法进行排序 策略是根据年龄
Arrays.sort(peopleList, new AgeSortStrategy());
for (Person person : peopleList) {
System.out.println(person);
}
System.out.println("根据身高排序:");
//使用public static <T> void sort(T[] a, Comparator<? super T> c) 方法进行排序 策略是根据身高
Arrays.sort(peopleList, new HeightSortStrategy());
for (Person person : peopleList) {
System.out.println(person);
}
}
}
分析:
- 我们可以根据自己的需要去选择比较的策略 而不像 实现Comparable接口那样比较策略只有一种,
购物的策略模式实现
public class Strategy02 {
/**
* 去购物有 谁去购物,出行的方式,则扣的力度
*/
static class GoShopping{
private String name;
//出行策略
private TravelStrategy travelStrategy;
//打折策略
private DiscountStrategy discountStrategy;
public GoShopping() {
}
public GoShopping(String name, TravelStrategy travelStrategy, DiscountStrategy discountStrategy) {
this.name = name;
this.travelStrategy = travelStrategy;
this.discountStrategy = discountStrategy;
}
@Override
public String toString() {
return "GoShopping{" +
"名字='" + name + '\'' +
", 出行方式=" + travelStrategy.travelMode() +
", 打折力度=" + discountStrategy.discountStrength() +
'}';
}
}
//出行方式的接口策略
interface TravelStrategy{
String travelMode();
}
//商品打折的接口策略
interface DiscountStrategy{
int discountStrength();
}
/**
* 出行方式为 坐公交车的策略
*/
static class BusTravelStrategy implements TravelStrategy{
@Override
public String travelMode() {
return "坐公交车去购物";
}
}
/**
* 出行方式为 骑自行车的策略
*/
static class BicycleTravelStrategy implements TravelStrategy{
@Override
public String travelMode() {
return "骑自行车去购物";
}
}
/**
* 打一折的策略
*/
static class OneDiscountStrategy implements DiscountStrategy{
@Override
public int discountStrength() {
return 1;
}
}
/**
* 打两折的策略
*/
static class TowDiscountStrategy implements DiscountStrategy{
@Override
public int discountStrength() {
return 2;
}
}
public static void main(String[] args) {
//new 出的对象可以根据自己的需要选择不同的策略
GoShopping goShopping1 = new GoShopping("小神",new BusTravelStrategy(),new OneDiscountStrategy());
GoShopping goShopping2 = new GoShopping("小神222",new BicycleTravelStrategy(),new TowDiscountStrategy());
System.out.println(goShopping1.toString());
System.out.println(goShopping2.toString());
}
}
优缺点分析
- 优点
- 算法可以自由切换
- 扩展性好,增加一个策略只需要实现接口就可以
- 缺点
- 当策略的数量过多的话,每个策略都是一个类,会使得复用性减少
- 所有的策略类都需要暴露