Skip to content

Instantly share code, notes, and snippets.

@klimeryk
Last active August 29, 2015 14:06
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 klimeryk/1b7143009fcfda12cd36 to your computer and use it in GitHub Desktop.
Save klimeryk/1b7143009fcfda12cd36 to your computer and use it in GitHub Desktop.
GWT's Activities & Places API and the visitor pattern (http://klimer.eu/2014/09/22/activities-places-and-the-visitor-pattern/)
public class AppActivityMapper implements ActivityMapper {
@Override
public Activity getActivity(Place place) {
activity = null;
if (place instanceof StartPlace) {
return new StartActivity();
} else if (place instanceof SearchPlace) {
return new SearchActivity();
} else if (place instanceof CustomerPlace) {
return new CustomerActivity();
}
return null;
}
}
public class AppActivityMapper implements ActivityMapper, PlaceVisitor {
private Activity activity;
@Override
public Activity getActivity(Place place) {
activity = null;
if (place instanceof AppPlace) {
((AppPlace) place).accept(this);
}
return activity;
}
@Override
public void visitStartPlace(StartPlace place) {
activity = injector.getStartActivity();
}
@Override
public void visitSearchPlace(SearchPlace place) {
activity = injector.getSearchActivity();
}
@Override
public void visitCustomerPlace(CustomerPlace place) {
activity = injector.getCustomerActivity();
}
}
public abstract class AppPlace extends Place {
public abstract void accept(PlaceVisitor visitor);
}
public class RootPresenter ... implements PlaceVisitor {
public RootPresenter(...) {
eventBus.addHandler(PlaceChangeEvent.TYPE, new PlaceChangeEvent.Handler() {
@Override
public void onPlaceChange(PlaceChangeEvent event) {
Place place = event.getNewPlace();
if (place instanceof AppPlace) {
((AppPlace) place).accept(RootPresenter.this);
}
}
});
}
@Override
public void visitStartPlace(StartPlace place) {
view.getStartButton.setActive(true);
// Or whatever else
}
// etc...
}
public class StartPlace extends AppPlace {
@Override
public void accept(PlaceVisitor visitor) {
visitor.visitStartPlace(this);
}
}
public class SearchPlace extends AppPlace {
@Override
public void accept(PlaceVisitor visitor) {
visitor.visitSearchPlace(this);
}
}
public class CustomerPlace extends AppPlace {
@Override
public void accept(PlaceVisitor visitor) {
visitor.visitCustomerPlace(this);
}
}
public interface PlaceVisitor {
void visitStartPlace(StartPlace place);
void visitSearchPlace(SearchPlace place);
void visitCustomerPlace(CustomerPlace place);
}
@jogardi
Copy link

jogardi commented Jan 7, 2015

I implemented this design and it was a great improvement. The only problem is that you had to cast to AppPlace. Casting should be avoided but this is pretty insignificant. Anyway, the way I see it, the whole reason that it's the AppActivityMappers 1 and 2 have to go through those acrobatics and downcast is because the Place was up-casted. When the place was originally created(Places are usually created in the Tokenizer) it was in it's downcast form. So a simple way of implementing this without any down casting is to go get the place in the Tokenizer.

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