Created
February 12, 2019 00:21
-
-
Save alexradzin/4082d5957a49747134bdab3d5ed94907 to your computer and use it in GitHub Desktop.
Improved Visitor
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package visitor; | |
public class Book implements Visitable { | |
private final String title; | |
private final int pageCount; | |
public Book(String title, int pageCount) { | |
this.title = title; | |
this.pageCount = pageCount; | |
} | |
public String getTitle() { | |
return title; | |
} | |
public int getPageCount() { | |
return pageCount; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package visitor; | |
public class Magazine implements Visitable { | |
private final String name; | |
private final int pageCountInVolume; | |
private final int volumes; | |
public Magazine(String name, int pageCountInVolume, int volumes) { | |
this.name = name; | |
this.pageCountInVolume = pageCountInVolume; | |
this.volumes = volumes; | |
} | |
public String getName() { | |
return name; | |
} | |
public int getPageCountInVolume() { | |
return pageCountInVolume; | |
} | |
public int getVolumes() { | |
return volumes; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package visitor; | |
import java.util.HashMap; | |
import java.util.Map; | |
public class Main { | |
private static void mapVisitorUsingConstructor() { | |
Book someBook = new Book("The Title", 200); | |
Magazine someMagazine = new Magazine("The name", 50, 12); | |
Map<Class<? extends Visitable>, MonoVisitor<? extends Visitable, Void>> printers = new HashMap<>(); | |
printers.put(Book.class, (MonoVisitor<Book, Void>) book -> { | |
System.out.println(book.getTitle()); | |
return null; | |
}); | |
printers.put(Magazine.class, (MonoVisitor<Magazine, Void>) magazine -> { | |
System.out.println("magazine"); | |
return null; | |
}); | |
MapVisitor<Void> printVisitor = new MapVisitor<>(printers); | |
someBook.accept(printVisitor); | |
someMagazine.accept(printVisitor); | |
Map<Class<? extends Visitable>, MonoVisitor<? extends Visitable, Integer>> pagesRetriever = new HashMap<>(); | |
pagesRetriever.put(Book.class, (MonoVisitor<Book, Integer>) Book::getPageCount); | |
pagesRetriever.put(Magazine.class, (MonoVisitor<Magazine, Integer>) magazine -> magazine.getPageCountInVolume() * magazine.getVolumes()); | |
MapVisitor<Integer> pageCountVisitor = new MapVisitor<>(pagesRetriever); | |
System.out.println(someBook.accept(pageCountVisitor)); | |
System.out.println(someMagazine.accept(pageCountVisitor)); | |
} | |
private static void mapVisitorUsingBuilder() { | |
Book someBook = new Book("The Title", 200); | |
Magazine someMagazine = new Magazine("The name", 50, 12); | |
Map<Class<? extends Visitable>, MonoVisitor<? extends Visitable, Void>> printers = new HashMap<>(); | |
printers.put(Book.class, (MonoVisitor<Book, Void>) book -> { | |
System.out.println(book.getTitle()); | |
return null; | |
}); | |
printers.put(Magazine.class, (MonoVisitor<Magazine, Void>) magazine -> { | |
System.out.println("magazine"); | |
return null; | |
}); | |
MapVisitor<Void> printVisitor = MapVisitor.builder(Void.class) | |
.with(Book.class, book -> {System.out.println(book.getTitle()); return null;}) | |
.with(Magazine.class, magazine -> {System.out.println(magazine.getName()); return null;}) | |
.build(); | |
someBook.accept(printVisitor); | |
someMagazine.accept(printVisitor); | |
Map<Class<? extends Visitable>, MonoVisitor<? extends Visitable, Integer>> pagesRetriever = new HashMap<>(); | |
pagesRetriever.put(Book.class, (MonoVisitor<Book, Integer>) Book::getPageCount); | |
pagesRetriever.put(Magazine.class, (MonoVisitor<Magazine, Integer>) magazine -> magazine.getPageCountInVolume() * magazine.getVolumes()); | |
MapVisitor<Integer> pageCountVisitor = new MapVisitor<>(pagesRetriever); | |
System.out.println(someBook.accept(pageCountVisitor)); | |
System.out.println(someMagazine.accept(pageCountVisitor)); | |
} | |
public static void main(String[] args) { | |
mapVisitorUsingConstructor(); | |
mapVisitorUsingBuilder(); | |
} | |
} | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package visitor; | |
import java.util.HashMap; | |
import java.util.Map; | |
import java.util.function.Function; | |
import java.util.function.Predicate; | |
public class MapVisitor<R> implements Function<Class<? extends Visitable>, MonoVisitor<? extends Visitable, R>>, Predicate<Class<? extends Visitable>> { | |
private final Map<Class<? extends Visitable>, MonoVisitor<? extends Visitable, R>> visitors; | |
public MapVisitor(Map<Class<? extends Visitable>, MonoVisitor<? extends Visitable, R>> visitors) { | |
this.visitors = visitors; | |
} | |
@Override | |
public MonoVisitor<? extends Visitable, R> apply(Class<? extends Visitable> clazz) { | |
return visitors.get(clazz); | |
} | |
public static <R> Builder<R> builder(Class<R> returnType) { | |
return new Builder<>(returnType); | |
} | |
@Override | |
public boolean test(Class<? extends Visitable> clazz) { | |
return visitors.containsKey(clazz); | |
} | |
public static class Builder<R> { | |
private final Class<R> returnType; | |
private final Map<Class<? extends Visitable>, MonoVisitor<? extends Visitable, R>> visitors = new HashMap<>(); | |
private Builder(Class<R> returnType) { | |
this.returnType = returnType; | |
} | |
public <V extends Visitable> Builder<R> with(Class<V> clazz, MonoVisitor<V, R> visitor) { | |
visitors.put(clazz, visitor); | |
return this; | |
} | |
public MapVisitor<R> build() { | |
return new MapVisitor<>(visitors); | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package visitor; | |
public interface MonoVisitor<T, R> { | |
R visit(T t); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package visitor; | |
import java.util.function.Function; | |
public interface Visitable <V extends Visitable> { | |
@SuppressWarnings("unchecked") | |
default <R> R accept(Function<Class<V>, MonoVisitor<V, R>> visitor) { | |
return visitor.apply((Class<V>)getClass()).visit((V)this); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
This is sample code for article https://alexradzin.blogspot.com/2019/02/New-life-of-old-Visitor-design-pattern.html