说明
在策略模式(Strategy Pattern)中,一个类的 行为 或其 算法 可以在 运行时更改。这种类型的设计模式属于行为型模式。
在策略模式中,我们创建表示各种策略的对象和一个行为随着策略对象改变而改变的 context 对象。策略对象改变 context 对象的执行算法。
一句话解释
方法的形参是 接口,该接口实现类 定义算法,即:方法中的 算法不是写死的,而是由 外部传入的
应用场景
策略模式,关注 类的行为,算法 是典型的行为,在有多种算法相似的情况下,使用 if...else 所带来的复杂和难以维护。
真实案例
- File.filter()
- Comparator
- Comparable
实现
- 定义一个行为(算法)接口
- 创建实现类,实现上面的接口,将算法写到该实现类中
优缺点
优点:
- 行为(算法)都实现了接口,所以可以 任意地替换
- 避免使用多重条件判断
- 扩展性良好
缺点:
- 策略类会增多
- 所有策略类都需要对外暴露。
案例
实现 school 类 ,有以下2个方法:
add(Student student):添加Student对象query(Querier querier):查询,该方法封装了大部分查询代码;并可以传入Querier接口实现类,该类可自定义查询条件(这里的条件相当于上文中的算法),如:查询姓李的,查询年龄大于20的,查询身高大于180cm的
Student
普通的bean
package strategy;
public class Student {
private String name;
private int age;
private String sex;
private int height;
public Student(String name, int age, String sex, int height) {
this.name = name;
this.age = age;
this.sex = sex;
this.height = height;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
", sex='" + sex + '\'' +
", height=" + height +
'}';
}
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 String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public int getHeight() {
return height;
}
public void setHeight(int height) {
this.height = height;
}
}
school 类(不合理)
该类有2个方法:
添加
Student类对象返回
学生 list,然后,遍历该学生 list,查询符合的条件,如:查询年龄大于20的。
注意:这种写法是不合理的,直接返回学生 list,程序员就有可能任意 删除学生、修改学生信息,这是不合理的。相当于程序员可以 任意操作 公务员名单,国企名单,这肯定是不行的
package strategy;
import java.util.ArrayList;
import java.util.List;
public class School {
private List<Student> studentList =new ArrayList<>();
public void add(Student student){
studentList.add(student);
}
public List<Student> get(){
return studentList;
}
}
下面是改进写法
查询条件接口
该接口只要一个方法 query(),
形参: Student 类对象
返回值: boolean 类型
true表示该学生符合条件;false表示该学生不符合条件
算法写在该接口的实现类中
package strategy;
//查询接口
public interface Querier {
/**
* 将算法写在该实现类的方法中
* @param s
* @return
*/
public boolean query(Student s);
}
school 类
该类有2个方法:
- 添加
Student类对象 - 查询方法,该方法可以传入
Querier查询条件接口。将自定义查询条件,写在Querier接口实现类中
package strategy;
import java.util.ArrayList;
import java.util.List;
public class School {
private List<Student> studentList =new ArrayList<>();
public void add(Student student){
studentList.add(student);
}
public List<Student> query(Querier querier){
List<Student> retList=new ArrayList<>();
for( Student item: studentList){
boolean b=querier.query(item);
if(b){
retList.add(item);
}
}
return retList;
}
}
根据年龄进行查询
算法类,要实现 Querier 接口
package strategy;
/**
* 算法实现类
* 继承 Querier 接口
*/
public class QueryAge implements Querier{
@Override
public boolean query(Student s) {
return s.getAge() < 20;
}
}
根据身高进行查询
算法类,要实现 Querier 接口
package strategy;
/**
* 算法实现类
* 继承 Querier 接口
*/
public class QueryLength implements Querier{
@Override
public boolean query(Student s) {
return s.getHeight() >180;
}
}
测试类
package strategy;
import java.util.List;
public class Test {
public static void main(String[] args) {
School school=new School();
Student lilei=new Student("李雷",20,"男",182);
school.add(lilei);
Student hanmeimei=new Student("韩梅梅",21,"女",165);
school.add(hanmeimei);
Student lucy=new Student("lucy",19,"女",172);
school.add(lucy);
Student lili=new Student("lili",19,"女",171);
school.add(lili);
//算法
Querier query = new QueryAge();
Querier query2 = new QueryLength();
List<Student> retList=school.query(query2);
for(Student s:retList){
System.out.println(s);
}
System.out.println();
}
}