Saturday, January 21, 2017

Passing code with behavior parameterize - Chapter 2

Behavior parameterization is the ability for a method to take multiple different behaviors as parameters and use them internally to accomplish different behaviors.

     · Behavior parameterization lets you make your code more adaptive to changing requirements and saves on engineering efforts in the future.

     · Passing code is a way to give new behaviors as arguments to a method. But it’s verbose prior to Java 8.
     
     ·  Anonymous classes helped a bit before Java 8 to get rid of the verbosity associated with declaring multiple concrete classes for an interface that are needed only once.

     ·  The Java API contains many methods that can be parameterized with different behaviors, which include sorting, threads, and GUI handling.

package com.java8.filteringApple_19Jan17;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.function.Predicate;

class Apple {
    private int weight = 0;
    private String color = "";

    public Apple(int weight, String color){
        this.weight = weight;
        this.color = color;
    }

    public Integer getWeight() {
        return weight;
    }

    public void setWeight(Integer weight) {
        this.weight = weight;
    }

    public String getColor() {
        return color;
    }

    public void setColor(String color) {
        this.color = color;
    }

    public String toString() {
        return "Apple{" +
               "color='" + color + '\'' +
               ", weight=" + weight +
               '}';
    }
}

interface AppleFormator {
     String accept(Apple a);
}

class FancyAppleFormator implements AppleFormator {
     public String accept(Apple a) {
           String size = a.getWeight() > 150 ? "Heavy" : "Light";
           return "A " + size + " apple of " + a.getColor() + " color";
     }
}

public class PrintApples {
     public static void main(String[] args) {
List<Apple> inventory = Arrays.asList(new Apple(80, "green"), new Apple(155, "black"), new Apple(120,"red"));
          
     /*Below process is verbose because you need to declare multiple classes that you instantiate only once*/
     prettyPrinApple(inventory, new FancyAppleFormator());

           /* Simply passing method implementation as a parameter */
           List<Apple> redApples = filterApples(inventory, p -> p.getColor().equals("red"));
           System.out.println(redApples);

           /* Sorting apples on basis of weight */
           inventory.sort((a1, a2) -> a1.getWeight().compareTo(a2.getWeight()));
           System.out.println("After Sorting inventory based on weight" + inventory);
          
           /* Sorting apples on basis of color */
           inventory.sort((a1,a2)-> a1.getColor().compareTo(a2.getColor()));
           System.out.println("After Sorting inventory based on color" + inventory);
     }

      /* Before Java8 implementation -1
      *  What if we can pass object of class, we could pass behavior of class directly as a parameter
      */
     static void prettyPrinApple(List<Apple> inventory, AppleFormator formattor) {
           for (Apple apple : inventory) {
                System.out.println(formattor.accept(apple));
           }
     }

     /* Using Predicate implementation -2 */
     public static List<Apple> filterApples(List<Apple> inventory, Predicate<Apple> p) {
           List<Apple> result = new ArrayList<>();
           for (Apple apple : inventory) {
                if (p.test(apple)) {
                     result.add(apple);
                }
           }
           return result;
     }
}

Output:

A Light apple of green color
A Heavy apple of black color
A Light apple of red color
[Apple{color='red', weight=120}]
After Sorting inventory based on weight[Apple{color='green', weight=80}, Apple{color='red', weight=120}, Apple{color='black', weight=155}]

After Sorting inventory based on color[Apple{color='black', weight=155}, Apple{color='green', weight=80}, Apple{color='red', weight=120}]

No comments:

Post a Comment