什么是策略设计模式
我们在完成一些需求的时候,有一些实现方式相同的需求,但是我们需要写很多重复性的代码逻辑去实现它。这个时候我们的相同的实现逻辑就可以理解为一个策略。我们可以吧这个逻辑提取出来当成一种策略,当我们要完成某一种需求的时候,我们就可以实施我们自己的策略去完成它。
示例
比如我们现在有一个员工表,表中有一些员工信息。 姓名,年龄,薪水。
/**
* @author wy
*/
@Data
public class Employee {
private String name;
private Integer age;
private Integer salary;
}
需求一
筛选出年龄大于30岁的员工信息。
@Test
public void test(){
ArrayList<Employee> employees = new ArrayList<>();
employees.add(new Employee("张三1",12,1000));
employees.add(new Employee("张三2",22,2000));
employees.add(new Employee("张三3",32,3000));
employees.add(new Employee("张三4",42,4000));
List<Employee> employees1 = filterEmployeeByAge(employees);
}
//传统方式,我们创建一个方法
public List<Employee> filterEmployeeByAge(ArrayList<Employee> employees){
List<Employee> em = new ArrayList<>();
//通过for循环去找到年龄大于30岁的员工
for (Employee employee: employees) {
if (employee.getAge()>30){
em.add(employee);
}
}
return em;
}
这样我们还没有感觉
当我们又有一个需求
需求二
筛选出薪水大于2000的员工
同样的传统方式我们加一个方法
public List<Employee> filterEmployeeBySalary(ArrayList<Employee> employees){
List<Employee> em = new ArrayList<>();
for (Employee employee: employees) {
if (employee.getSalary()>2000){
em.add(employee);
}
}
return em;
}
我们比较这两个方法,我们会发现,这两个方法中就只有它们的if判断中的条件不一样,其他地方的代码都是一样的。
当我们又有需求的时候比如按照xxx属性去筛选,我们就又要去写一个一样的方法,改一下条件。
这样我们的代码就非常的冗余。
这个时候我们可以对我们的代码使用策略模式进行优化。
使用策略模式优化
优化一、使用策略类
我们设置一个接口,我们每一个类都去继承他,形成一个策略类。这样我们可以根据需求形成对应的策略。
/**
* @author wy
*/
public interface MyFilter<T> {
public boolean filter(T t);
}
创建一个通过年龄进行过滤的策略
/**
* @author wy
*/
public class FilterEmployeeByAge implements MyFilter<Employee> {
@Override
public boolean filter(Employee employee) {
return employee.getAge()>30;
}
}
这样的话我们就可统一一个方法。让这个方法去实行我们自己的策略。
@Test
public void test(){
ArrayList<Employee> employees = new ArrayList<>();
employees.add(new Employee("张三1",12,1000));
employees.add(new Employee("张三2",22,2000));
employees.add(new Employee("张三3",32,3000));
employees.add(new Employee("张三4",42,4000));
//通过自己的策略进行筛选
System.out.println(filterEmployee(employees,new FilterEmployeeByAge()));
}
//统一的过滤方法
public List<Employee> filterEmployee(List<Employee> employees, MyFilter<Employee> em){
ArrayList<Employee> employees1 = new ArrayList<>();
for (Employee e: employees) {
if (em.filter(e)){
employees1.add(e);
}
}
return employees1;
}
比如第二个需求,我们一样的可以创建一个策略类。
/**
* @author wy
*/
public class FilterEmployeeBySalary implements MyFilter<Employee> {
@Override
public boolean filter(Employee employee) {
return employee.getSalary()>2000;
}
}
同样的我们可以去使用我们的策略。
@Test
public void test(){
ArrayList<Employee> employees = new ArrayList<>();
employees.add(new Employee("张三1",12,1000));
employees.add(new Employee("张三2",22,2000));
employees.add(new Employee("张三3",32,3000));
employees.add(new Employee("张三4",42,4000));
// System.out.println(filterEmployee(employees,new FilterEmployeeByAge()));
System.out.println(filterEmployee(employees, new FilterEmployeeBySalary()));
}
这样我们就可以增加我们的策略去完成相应的需求
优化二、使用匿名内部类
通过上边的优化可能觉得这些策略类写起来也有相同的重复的东西,像实现接口、重写方法。
我们接下来还可以通过匿名内部类的方式去简化。
List<Employee> employees1 = filterEmployee(employees, new MyFilter<Employee>() {
@Override
public boolean filter(Employee employee) {
return employee.getAge() > 30;
}
});
System.out.println(employees1);
List<Employee> employees2 = filterEmployee(employees, new MyFilter<Employee>() {
@Override
public boolean filter(Employee employee) {
return employee.getSalary() > 1000;
}
});
System.out.println(employees2);
优化三、使用lambda表达式
上边的方法我们又会发现,在我们的匿名内部类中,除了我return不同,其他的都是相同的。
说到这里我们就会想起来使用lambda表达式去进行优化
List<Employee> employees1 = filterEmployee(employees, (e) -> e.getAge() > 30);
employees1.forEach(System.out::println);
List<Employee> employees2 = filterEmployee(employees, (e) -> e.getSalary() > 1000 & e.getSalary()<3000);
employees2.forEach(System.out::println);
优化四、Stream API
通过上边的优化,又有人说了,我就是懒,我这还得写接口,还得创建方法。我不想写。
好的、我们同样可以完成
@Test
public void test() {
ArrayList<Employee> employees = new ArrayList<>();
employees.add(new Employee("张三1", 12, 1000));
employees.add(new Employee("张三2", 22, 2000));
employees.add(new Employee("张三3", 32, 3000));
employees.add(new Employee("张三4", 42, 4000));
employees.stream()
.filter((e)->e.getAge()>20)
.forEach(System.out::println);
}
?
?
|