Skip to content

Instantly share code, notes, and snippets.

@alexradzin
Created February 22, 2023 09:45
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 alexradzin/1331d23ce1da15ce75076d21341ba483 to your computer and use it in GitHub Desktop.
Save alexradzin/1331d23ce1da15ce75076d21341ba483 to your computer and use it in GitHub Desktop.
Evaluator: alternative to the Visitor pattern
package visitoralternative;
public interface Bird {
}
package visitoralternative;
public class Duck implements Bird {
}
package visitoralternative;
public class Eagle implements Bird {
}
package visitoralternative;
import java.util.Comparator;
import java.util.Map;
import java.util.Optional;
import java.util.TreeMap;
import java.util.function.Function;
public class Evaluator<T, R> {
private final Map<T, Function<T, R>> map;
public Evaluator(Map<T, Function<T, R>> map, Comparator<T> comparator) {
this.map = new TreeMap<>(comparator);
this.map.putAll(map);
}
public R eval(T o) {
return Optional.ofNullable(map.get(o)).orElseThrow(UnsupportedOperationException::new).apply(o);
}
public boolean isSupported(T o) {
return map.containsKey(o);
}
}
package visitoralternative;
import java.util.Comparator;
import java.util.Map;
public class EvaluatorDemo {
public static void main(String[] args) {
Evaluator<Bird, String> walk = new Evaluator<>(
Map.of(
new Ostrich(), bird -> birdName(bird) + " walks",
new Penguin(), bird -> birdName(bird) + " walks",
new Eagle(), bird -> birdName(bird) + " walks",
new Duck(), bird -> birdName(bird) + " walks"
),
Comparator.comparing(o -> o.getClass().getName()));
Evaluator<Bird, String> fly = new Evaluator<>(
Map.of(
new Eagle(), bird -> birdName(bird) + " flies",
new Swifts(), bird -> birdName(bird) + " flies",
new Duck(), bird -> birdName(bird) + " flies"
),
Comparator.comparing(o -> o.getClass().getName()));
Evaluator<Bird, String> swim = new Evaluator<>(
Map.of(
new Penguin(), bird -> birdName(bird) + " swims",
new Duck(), bird -> birdName(bird) + " swims"
),
Comparator.comparing(o -> o.getClass().getName()));
Duck duck = new Duck();
Swifts swifts = new Swifts();
Penguin penguin = new Penguin();
System.out.println("Duck " + can(walk.isSupported(duck)) + " walk");
System.out.println("Duck " + can(fly.isSupported(duck)) + " fly");
System.out.println("Duck " + can(swim.isSupported(duck)) + " swim");
System.out.println(walk.eval(duck));
System.out.println(fly.eval(duck));
System.out.println(swim.eval(duck));
System.out.println("Penguin " + can(walk.isSupported(penguin)) + " walk");
System.out.println("Penguin " + can(fly.isSupported(penguin)) + " fly");
System.out.println("Penguin " + can(swim.isSupported(penguin)) + " swim");
System.out.println(walk.eval(penguin));
System.out.println(swim.eval(penguin));
System.out.println("Swifts " + can(walk.isSupported(swifts)) + " walk");
System.out.println("Swifts " + can(fly.isSupported(swifts)) + " fly");
System.out.println("Swifts " + can(swim.isSupported(swifts)) + " swim");
System.out.println(fly.eval(swifts));
}
private static String birdName(Bird bird) {
return bird.getClass().getSimpleName();
}
private static String can(boolean can) {
return can ? "can": "cannot";
}
}
package visitoralternative;
public class Ostrich implements Bird {
}
package visitoralternative;
public class Penguin implements Bird {
}
package visitoralternative;
public class Swifts implements Bird {
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment