Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Chain style method design

Tags:

java

oop

I wrote a simple class to demonstrate a chain style method design:

public class Cal {

    private Cal(){}

    private boolean isCheckArguments = false;

    public static Cal useAbs() {
        return new Cal(){   
          @Override int check(int i) {
                return Math.abs(i);
            }};
    }

    public static Cal useNormal() {
        return new Cal();
    }   

    public Cal checkArguments() {
        isCheckArguments =true;
        return this;
    }

     int check(int i){ return i;}

     public int plus(int i, int j) {    
        if(isCheckArguments && i<j){
            throw new IllegalArgumentException("i<j!");
        }
        return check(i+j);
    }
}

So the client code can be:

Cal cal = Cal.useAbs().checkArguments();
int sum = cal.plus(100,2);//IllegalArgumentException occurs

Cal cal2 = Cal.useAbs();
int sum2 = cal.plus(-100,2);//98

Cal cal3 = Cal.useNormal();
int sum3 = cal.plus(-100,2);//-98

My question is: Is it a reasonable design? comparing to: int plus(int a, int b, boolean useAbs, boolean checkArguments). Thanks!

like image 297
卢声远 Shengyuan Lu Avatar asked Apr 25 '11 15:04

卢声远 Shengyuan Lu


1 Answers

Sounds like you want a fluent interface to build a service class. Guava does similar things. You'd do something like this:

public interface Cal {
   int plus(int a, int b);
}

public class CalBuilder {
    class InternalCal implements Cal {
       boolean useAbs;
       boolean checkArgs;
       public int plus(int a, int b) {
          if(checkArgs) {
             // blah, blah blah
          }
          if(useAbs) {
             // doodle bug, doodle darn
          }
          return a+b; // whatevs
       }
    }
    boolean absSet=false;
    InternalCal holder=new InternalCal();
    public CalBuilder useNormal() {
        if(absSet) { throw new IllegalArgumentException(); } // already called
        holder.useAbs=false;    
        absSet=true;
        return this;
    }

    public CalBuilder useAbs() {
        if(absSet) { throw new IllegalArgumentException(); } // already called
        holder.useAbs=false;    
        absSet=true;
        return this;
    }

    public CalBuilder checkArguments() {
       if(holder.checkArgs) { throw new IllegalArgumentException(); }
       holder.checkArgs=true;
       return this;
    }

    public Cal build() {
       return holder;
    }
}

Usage would look like this:

Cal cal=new CalBuilder().useAbs().checkArguments().build();
int sum=cal.plus(1,2);
like image 190
Joseph Ottinger Avatar answered Sep 20 '22 15:09

Joseph Ottinger