Skip to content

Instantly share code, notes, and snippets.

@adamv
Last active July 26, 2016 05:21
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save adamv/8eef51f55b5ecefdbb103e012120c139 to your computer and use it in GitHub Desktop.
Save adamv/8eef51f55b5ecefdbb103e012120c139 to your computer and use it in GitHub Desktop.
package codenotes;
public class Main {
public static void main(String[] args) {
Result r = new Result(Result.FIRST_NAME_FLAG|Result.LAST_NAME_FLAG|Result.ADDRESS_FLAG);
Result.Match m1 = Result.Match.atLeast().firstName().lastName();
System.out.println(r.matches(m1)); // true
Result.Match m2 = Result.Match.exactly().firstName().lastName().address();
System.out.println(r.matches(m2)); // true
Result.Match m3 = Result.Match.exactly().firstName().lastName();
System.out.println(r.matches(m3)); // false
Result.Match m4 = Result.Match.atLeast().firstName().phone();
System.out.println(r.matches(m4)); // false
}
}
package codenotes;
import java.util.Objects;
/**
* A service result.
*
* A result can match on lots of different stuff, so introduce a Match
* class that allows clients of this code to query what was matched on.
*/
public class Result {
public static int FIRST_NAME_FLAG = 1;
public static int LAST_NAME_FLAG = 2;
public static int ADDRESS_FLAG = 4;
public static int PHONE_FLAG = 8;
/**
* Match instances are immutable and contain their own builder. To
* construct one, start with `atLeast()` or `exactly()` and chain the
* methods corresponding to the stuff that you want to match.
*/
public static class Match {
boolean matches(int matchedThings) {
switch (mode) {
case AT_LEAST:
return (matchedThings & flags) == flags;
case EXACTLY:
return matchedThings == flags;
default:
throw new IllegalStateException("Illegal match mode " + mode);
}
}
enum Mode { AT_LEAST, EXACTLY }
private final Mode mode;
private final int flags;
Match(Mode mode, int flags) {
Objects.requireNonNull(mode);
this.mode = mode;
this.flags = flags;
}
public static Match atLeast() {
return new Match(Mode.AT_LEAST, 0);
}
public static Match exactly() {
return new Match(Mode.EXACTLY, 0);
}
public Match firstName() {
return new Match(this.mode, this.flags | FIRST_NAME_FLAG);
}
public Match lastName() {
return new Match(this.mode, this.flags | LAST_NAME_FLAG);
}
public Match address() {
return new Match(this.mode, this.flags | ADDRESS_FLAG);
}
public Match phone() {
return new Match(this.mode, this.flags | PHONE_FLAG);
}
}
private final int matchedThings;
public Result(int matchedThings) {
this.matchedThings = matchedThings;
}
public boolean matches(Match match) {
return match.matches(this.matchedThings);
}
}
@adamv
Copy link
Author

adamv commented Jul 26, 2016

Defining boolean matches(int flags) on Result seems simpler to me, but in case I need to embiggen the interface...

@adamv
Copy link
Author

adamv commented Jul 26, 2016

A more by-the-book approach would replace the Mode enum and switch statement with two subclasses, but let's not get hung up on the details here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment