Preface:
The following content comes from the book java8 practice. I will sort out the contents learned in the book, so as to make it convenient for busy little friends to get started quickly and practice java8
Text:
Suppose an apple farmer has harvested a garden of apples, and he needs you to select satisfactory apples according to his conditions
First, let's create an Apple class
public class Apple { /** * weight */ private Integer weight; /** * colour */ private String color;
getter();
setter();
toString();
... }
He said: I need to pick out the red apples
public void filterRedApple(List<Apple> appleList){ for(Apple apple : appleList){ if("red".equals(apple)){ System.out.println("Red apple"); } } }
He said: I want to pick out the green apples
Just think about it. Let's take color as a parameter
public void filterGreenApple(List<Apple> appleList , String color) { for (Apple apple : appleList) { if (color.equals(apple)) { System.out.println("Green apple"); } } }
He said: I need to pick out 150g apples
public void filterWeightApple(List<Apple> appleList,Integer weight) { for (Apple apple : appleList) { if (apple.getWeight() > weight) { System.out.println("Weight over 150 g Apple"); } } }
He said: I want to pick out more than 100g of red apples
public void filterAppleByWeightAndColor(List<Apple> appleList,String color,Integer weight){ for (Apple apple : appleList) { if (apple.getWeight() > weight && color.equals(apple.getColor())) { System.out.println("Weight greater than 100 g Red apple"); } } }
In the face of endless demand changes, we need to constantly adapt
Let's see how to improve
Create a new Apple filter interface
public interface ApplePredicate { /** * Screening apples */ boolean test(Apple apple); }
Then we implement the screening method separately
Filter by color
public class FilterRedApple implements ApplePredicate { @Override public boolean test(Apple apple) { return "red".equals(apple.getColor()) ? true : false; } }
Filter by weight
public class FilterWeightApple implements ApplePredicate { @Override public boolean test(Apple apple) { return apple.getColor() > 100 ? true : false; } }
Filter by color and weight
public class FilterAppleByColorAndWeight implements ApplePredicate { @Override public boolean test(Apple apple) { return "red".equals(apple.getColor()) && apple.getWeight > 100 ? true : false; } }
For example, he wants red apples
Let's do this for him
public static void filterApple(List<Apple> appleList , ApplePredicate p) { for (Apple apple : appleList) { if (p.test(apple)) { System.out.println("This is the apple you want" + apple.toString()); } } }
When we call, just pass in its implementation class
public static void main(String[] args) { filterApple(appleList, new FilterRedApple()); filterApple(appleList, new FilterWeightApple()); }
Let's look at the difference between the current method and the original method:
The original method is to write a new method to implement each requirement, so that the code will be very cumbersome and redundant, because they are actually doing the same thing: screening the desired apple, just under different conditions
Our improved method is: write a filter interface, and then implement the interface separately. For example, if you want a red apple, write an implementation of sun selected red apple, and if you want a big apple, write a new implementation
It's kind of like a strategic model
Well. We've done a cool thing: the behavior of the fliterApple method depends on the code we pass through the ApplePredicate object. This is behavior parameterization, which can help us write flexible API s
Now, some students may ask me if it is too troublesome to write a new implementation class for each new requirement. We can use anonymous classes to implement it
Indeed, we can use anonymous classes to implement
public static void main(String[] args) {
filterApple(appleList, new ApplePredicate() {
@Override public boolean test(Apple apple) { return "red".equal(apple.getColor) ? true : false; } });
}
Although anonymous classes improve the verbosity of writing several implementation classes for an interface to some extent, they still need to create an object specific implementation method to define a new behavior
So, I prefer to use the form of behavior parameterization
Concept:
Behavior parameterization: the ability of a method to accept multiple different behaviors as parameters and use them internally to complete different behaviors
Behavior parameterization can make the code better adapt to the changing needs and reduce the workload in the future
Passing code: passing a new behavior as a parameter to a method