Java 8 (1) Behavior parameterization

Source: Internet
Author: User
Tags getcolor

Behavioral parameterization is a software development model that can help you handle frequent change requirements. It means to take out a block of code, get it ready but not execute it. This block of code can later be called by other parts of your program, which means you can postpone the execution of this code. For example: You can pass a block of code as an argument to another method and then execute it later.

Responding to changing needs

1. First try: Implement a feature that filters out the green Apple functionality from a list.

Prepare the Apple entity class first

 Public class Apple {    private  Integer Id;     Private String Color;     Private Double Weight;     //getter. Setter.. ToString.. }

Write the function of filtering out green apples

     Public Static List<apple> filter (list<apple> apples) {        Listnew arraylist<>();          for (Apple apple:apples) {            // filter out green apples             if("green" ) . Equals (Apple.getcolor ())) {                result.add (apple);            }        }         return result;    }

Test data

 public  static  void   main (string[] args) {List  <Apple> apples = Arrays.aslist ( new  Apple (1, "green", 18.0 new  Apple (2, "Yellow" ,36d",  new  Apple (3, "Red"                 , 42d),  new  Apple (4, "green" ,15d),         new  Apple (5, "Red" ,16d));        List  <Apple> greenapple = filter (apples);    System.out.println (greenapple); }

Output Result:

[Apple{id=1, color= ' green ', weight= ' 18.0 '}, apple{id=4, color= ' green ', weight= ' 15.0 '}]

To realize the function, now the product said I want to filter the Red Apple, the simplest way is to copy this method, the name is changed to Filterredapples, and then change the if condition to match the red Apple, but the product wants to filter more colors of apples, yellow, orange, big mole, etc. This method is not going to be the color as a parameter

2. Second attempt: color as a parameter

    // use color as a parameter     Public Static List<apple> filterapplesbycolor (list<apple> apples,String color) {        ListNew arraylist<>();          for (Apple apple:apples) {            if(Color.equals (Apple.getcolor ())) {                Result.add (apple);            }        }         return result;    }

Now just call this, and the product will be satisfied.

list<apple> yellowapple = Filterapplesbycolor (apples, "yellow"); List<Apple> redapple = Filterapplesbycolor (apples, "red");

Then the product ran over to say, if can distinguish Apple size is too good, more than 32 divided into big apples, less than 32 is divided into small apples.

So you took the following method, and added the weight of the parameter

    // To filter apples    by weight  Public Static List<apple> filterapplesbyweight (list<apple> apples,Double weight) {        ListNew arraylist<>();          for (Apple apple:apples) {            if(apple.getweight () >   weight) {                Result.add (apple);            }        }         return result;    }

You have finally achieved the demand for the product, but note that you copied most of the code to implement the traversal of the Apple list and filter the criteria for each apple. This is a bit disappointing because it breaks the software engineering principles of don ' t Repeat yourself (don't repeat yourself).

3. Third attempt: Filter every attribute you can think of

You can combine color and weight into one method, called Filtercolororweight, and then add a parameter to distinguish which property needs to be filtered.

    //Filter by color or by weight     Public StaticList<apple> filtercolororweight (list<apple> apples, String color, Double weight,Boolean flag) {List<Apple> result =NewArraylist<>();  for(Apple apple:apples) { if (flag && color.equals (apple.getcolor)) | | (!flag && apple.getweight () > weight))            { result.add (Apple); }        }        returnresult; }

Then you can use this:

list<apple> yellowapples = filtercolororweight (apples, "yellow", 0d,true); List<Apple> bigapples = filtercolororweight (Apples, "", 32d,false);

This solution is no worse, first the client code looks rotten, what does true and false mean? In addition, the solution is not a good area to cope with the changing needs, if the product lets you to the other different properties of Apple screening, such as size, shape, origin, etc., what should be done? Or ask you to combine attributes to make more complex queries, such as Big green apples, what should I do?

Parameterization of Behavior

As you can see in the previous section, you need a better way to cope with the changing needs than to add a lot of parameters. One solution is to model the criteria you choose: For example, to return a Boolean value based on some of Apple's properties (whether green or not), we call it a predicate . Let's start by defining an excuse to model the selection criteria.

 Public Interface applepredicate {    boolean  Test (Apple apple);}

You can now use multiple implementations of applepredicate to represent different criteria for selection, such as:

 public  class  Applegreencolorpredicate implements   applepredicate {//green apple verb   public  Span style= "COLOR: #0000ff" >boolean   Test (Apple Apple) { return " green ".equals (Apple.getcolor ()); }}
 Public class Implements applepredicate {    //Big Apple predicate      public boolean  Test (Apple apple) {         return apple.getweight () >;    }}

Now, you can think of these criteria as different behaviors of the filter method. What you just did. These are related to the "policy design pattern", which allows you to define a set of algorithms, encapsulate them (as "policies"), and then select an algorithm at run time. Here, Applepredicate is the algorithm group, the different strategies are appleheavyweightpredicate and applegreencolorpredicate.

You need the Filterapples method to accept the Applepredicate object and do a conditional test on Apple. This is behavior parameterization: Allow methods to accept multiple behaviors (or strategies) as parameters and use them internally to accomplish different behaviors.

4. Fourth attempt: filtering based on abstract criteria

    // Filter by abstract criteria     Public Static List<apple> filterapples (list<apple> apples,applepredicate p) {        ListNew Arraylist<>();          for (Apple apple:apples) {            if(p.test (Apple)) {                result.add (Apple);            }        }         return result;    }

This is used when:

list<apple> greenapple = Filterapples (apples,new  applegreencolorpredicate ()); List<Apple> bigapple = filterapples (apples,new appleheavyweightpredicate ());

1. Passing Code/behavior

Here we can celebrate a little bit more flexible than the first time we tried, and it's easier to read and use! Now you can create different applepredicate objects and pass them to the Filterapples method. For example, now that the product lets you find all the red apples weighing more than 80 grams, you just need to create a class to implement Applepredicate, your code is now flexible enough to deal with any design Apple attribute needs change:

 Public class Implements applepredicate {    @Override    publicboolean  Test (Apple apple) {          return "Red". Equals (Apple.getcolor ()) && apple.getweight () >;    }}

Passed to the Filterapples method without modifying the internal implementation of the Filterapples method:

list<apple> redbigapple = Filterapples (apples,new appleredandbigpredicate ());

Now you've done a cool thing:The behavior of the Filterapples method depends on the code you pass through the Applepredicate object. In other words, you parameterize the behavior of the Filterapples Method!

In the previous example, the only important code is the implementation of the test method, which formally defines the new behavior of the Filterapples method. Since the Filterapples method can only accept objects, you must wrap the code in the Applepredicate object. This approach is similar to "passing code" inline, because you pass a Boolean expression through an object that implements the test method.

2. Multiple behaviors, one parameter

The advantage of the behavior parameterization is that you can separate the logic that traverses the collection from the logic of each element in the collection. This allows you to reuse the same method and give it different behaviors to achieve different purposes.

Behavioral parameterization Exercises

Write the Printapple method to implement a feature that generates a string output in a variety of ways based on Apple (for example, you can let the Printapple method only print each Apple color, or let it print what color big (small) apple)

Creating the Appleformater interface

 Public Interface Appleformater {    String accept (Apple a);}

Create Appleweightformater, Applecolorformater to implement interfaces

 Public class Implements appleformater {    @Override    public  String Accept (Apple a) {        return ] This is a "+ a.getcolor () +" + (A.getweight () > 32? "Big": "small") + "Apple";    }}
 Public class Implements appleformater {    @Override    public  String Accept (Apple a) {          Return "one" + a.getcolor () + "Apple";    }}

Then create the Printapple method to pass a different Formater object to it

     Public Static void printapple (list<apple> apples,appleformater af) {        for  (Apple Apple:apples) {            =  af.accept (apple);            SYSTEM.OUT.PRINTLN (output);        }    }

Test:

Newnew applecolorformater ());

Now you can abstract the behavior and make your code more responsive to changes in requirements, but the process is verbose because you need to declare a lot of classes that are instantiated only once.

Anonymous class

Use anonymous classes to deal with these classes that only need to be used once.

For example, using anonymous classes to add a new print style: Wow, this is a Big Apple ah?

New Appleformater () {  public  String Accept (Apple a) {    return "Wow, this is a" + ( A.getweight () > 32? "Big": "small") + "Apple ah?" ";  }});

Using anonymous classes solves the verbose problem of declaring several entity classes for an interface, but it is still unsatisfactory.

Using lambda expressions

The above code can be overridden with a lambda expression to look like this:

 - "Wow, this is a" + (A.getweight () > 32? "Big": "small") + "Apple ah?" ");

Does that look more refreshing than that? More like a description of the problem itself! About Lambda will be described in the next section.

Abstracting the list type

Currently the Filterapples method is only available for Apple and can abstract the list type so that it supports bananas, oranges, integers, or string lists!

 Public Interface Predicate<t> {    boolean  Test (T-t);}
     Public static <T> list<t> filter (list<t> list, predicate<t> p) {        listnew arraylist<>();          for (T e:list) {            if(P.test (e)) {                result.add (e);            }        }         return result;    }

Test:

List<apple> greenapple = filter (apples, apple apple), "green". Equals (Apple.getcolor ())); System.out.println (greenapple); List<Integer> evennumbers = Filter (Arrays.aslist (1,2,3,4,5,6,10), (Integer i), i%2 ==0); System.out.println (evennumbers);

Handsome, not handsome? You now find the best balance between flexibility and indirection, which is impossible before Java 8!

A real example

As you can see now, behavioral parameterization is a useful pattern that adapts easily to changing needs. This pattern encapsulates a behavior (a piece of code) and parameterize the behavior of the method by passing and using the behavior of the dress (for example, different verbs to apple).

1. Use Comparator to sort

Sorting a collection is a common task, for example, a product that wants to sort by Apple's weight. In Java 8, the list comes with a sort method (you can also use Collections.sort). The sort behavior can be parameterized with the Java.util.Comparator object, which has the following interface:

 Package java.util; @FunctionalInterface  Public Interface Comparator<t> {    int  compare (t O1, T O2);}

Therefore, you can create comparator implementations at any time, sort them by using sort methods, and use anonymous classes in ascending order of weight:

Apples.sort (new comparator<apple>() {        @Override         publicint  Compare (Apple O1, Apple O2) {            return  o1.getweight (). CompareTo (O2.getweight ()) ;         }});

Use lambda as follows:

Apples.sort (Apple a1,apple A2), A1.getweight (). CompareTo (A2.getweight ()));

2. Executing a code block with runnable

Threads are like lightweight processes: they execute a block of code themselves. In Java, you can use the Runnable interface to represent a block of code to execute.

 Package Java.lang; @FunctionalInterface  Public Interface Runnable {        publicabstractvoid  run ();}

Use anonymous classes to create threads that perform different behaviors:

New Thread (new  Runnable () {    @Override    publicvoid  run () {        System.out.println ("t111");}    );

Using lambda:

New Thread ((), System.out.println ("t2222"));

Summary:

1. Behavior parameterization, is a method to accept a number of different behaviors as parameters, and use them internally, the ability to complete different behaviors.

2. Behavioral parameterization allows code to better adapt to changing needs and reduce future workloads.

3. Passing the code means passing the new behavior as a parameter to the method, which is verbose before Java 8. Verbose code that declares many of the entity classes that are used only once for an interface can be reduced by using anonymous classes before Java 8.

The 4.java API contains many methods that can be parameterized with different behaviors, including sorting, threading, and so on.

Java 8 (1) Behavior parameterization

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.