Java8 real - passing through behavioral parameters of the code

Disclaimer: This article is a blogger original article, shall not be reproduced without the bloggers allowed. https://blog.csdn.net/sinat_22797429/article/details/82320747

table of Contents

Preface

Java8 contact with for some time, found that this stuff is really good, many large companies are using cattle, I bought a book "Java8 combat", read some of the contents of the book do some study notes.

Test chopper: Screening of green apple

The first problem may be solved like this:

    public static List<Apple> filterGreenApples(List<Apple> inventory){
        List<Apple> result = new ArrayList<Apple>();
        for(Apple apple: inventory){
            if("greeen".equals(apple.getColour())){
                result.add(apple);
            }
        }
        return result;
    }

The above is for us to filter out Green Apple program, demand is constantly changing thing! Farmers now changed my mind, Apple wants to filter out other colors such as light green, dark red, yellow and so on. Our first thought is that it is abstract.

And then show their skills: the color as a parameter

When requirements change, our first thought is to color as a parameter, then the flexibility to adapt to change:

public static List<Apple> filterGreenApples(List<Apple> inventory, String colour){
        List<Apple> result = new ArrayList<Apple>();
        for(Apple apple: inventory){
            if(colour.equals(apple.getColour())){
                result.add(apple);
            }
        }
        return result;
    }

This time can be screened by the color of it to meet the requirements of Apple, now the farmers need to filter out the apple weighing more than 150g, which is how to achieve it? You might think this is implemented:

public static List<Apple> filterGreenApples(List<Apple> inventory, long weight){
        List<Apple> result = new ArrayList<Apple>();
        for(Apple apple: inventory){
            if(apple.getWeight() > weight){
                result.add(apple);
            }
        }
        return result;
    }

Such indeed meet the demand, but copied a lot of code, does not meet the principles of software engineering, then you can increase the way a flag to distinguish color and weight of the inquiry. So you think this in the following way:

Third try: For each property you want to do screening

public static List<Apple> filterGreenApples(List<Apple> inventory, String colour, long weight, boolean flag){

        List<Apple> result = new ArrayList<Apple>();
        for(Apple apple: inventory){
            if((flag&&apple.getWeight() > weight)||
                    (!flag&&apple.getColour().equals(colour))){
                result.add(apple);
            }
        }
        return result;
    }

So you can control the screening of two properties by a method that is not feeling very witty? But it makes the program look very clumsy, if farmers need to filter out the size, shape, origin. How to do it? In the next section, we will use parameterized behavior to achieve this flexibility.

Parameterized behavior

Our first thought is given to the selection of an interface standard for modeling:

interface ApplePredicate{
    boolean test(Apple apple);
}

class AppleHeavyWeightPredicate implements ApplePredicate{
    public boolean test(Apple apple) {
        return apple.getWeight() >150;
    }
}

class AppleGreenColorPredicate implements ApplePredicate{
    public boolean test(Apple apple) {
        return "green".equals(apple.getColour());
    }
}

Operation and above "strategy design pattern" relevant done, so that a method of receiving a variety of behavior as a parameter, and is used internally to perform different actions.

According to the abstract screening conditions

    public class GreenApple {

    public static List<Apple> filterApples(List<Apple> inventory, ApplePredicate p){

        ArrayList<Apple> result = new ArrayList<>();
        for(Apple apple: inventory){
            if(p.test(apple)){
                result.add(apple);
            }
        }
        return result;
    }

    public static class AppleRedAndHeavyPredicate implements ApplePredicate{

        @Override
        public boolean test(Apple apple) {
            return "red".equals(apple.getColour())&&apple.getWeight() > 150;
        }
    }

    public static void main(String[] args) {

        Apple apple = new Apple();
        apple.setColour("green");
        apple.setWeight(12);

        Apple apple2 = new Apple();
        apple2.setColour("red");
        apple2.setWeight(288);

        ArrayList<Apple> inventory = new ArrayList<Apple>();
        inventory.add(apple);
        inventory.add(apple2);

        List<Apple> apples = GreenApple.filterApples(inventory, new AppleRedAndHeavyPredicate());

    }
}

In this way, farmers simply create a class that implements the interface ApplePredicate on the line, you can define the rules you want to filter in this class there, so that you can conduct a parametric method filterApples.

Anonymous inner classes

List<Apple> redApples = filterApples(inventory, new ApplePredicate() {
            @Override
            public boolean test(Apple apple) {
                return "red".equals(apple.getColour());
            }
        });

While this can be, but the program will significantly awkward

Use Lambda Expressions

Lambda expressions make use of the program looks very clean and tidy

            List<Apple> result=filterApples(inventory,(Apple apple1) ->"red".equals(apple1.getColour()));

Apple may even omit the type, because it is only one way

        List<Apple> result=filterApples(inventory,apple1 ->"red".equals(apple1.getColour()));

The List abstract type

On your way to the abstract, in fact, we can do better! You can List abstract type, which go beyond the issue you want to deal with the current

List<Apple> redApple = filter(inventory, (Apple apple) -> "red".equals(apple.getColour()));
        List<String> str = filter(numbers, (Integer i) -> i % 2 == 0);
public static  <T>List<T> filter(List<T> list, Predicate<T> p){
        List<T> result = new ArrayList<>();
        for(T e:list){
            if(p.test(e)){
                result.add(e);
            }
        }
        return result;
    }

summary

Behavioral parameters of: is a method of receiving a plurality of different behaviors as a parameter, and use them internally, the ability to perform different behaviors
transmission codes : a new behavior is to a method to pass parameters

Guess you like

Origin blog.csdn.net/sinat_22797429/article/details/82320747