I'm just trying to understand the main benefits of using the Visitor pattern.
Here's a sample Java implementation
///////////////////////////////////
// Interfaces
interface MamalVisitor {
void visit(Mammal mammal);
}
interface MammalVisitable {
public void accept(MamalVisitor visitor);
}
interface Mammal extends MammalVisitable {
public int getLegsNumber();
}
///////////////////////////////////
///////////////////////////////////
// Model
class Human implements Mammal {
#Override
public void accept(MamalVisitor visitor) { visitor.visit(this); }
#Override
public int getLegsNumber() { return 2; }
}
//PIRATE HAS A WOOD LEG
class Pirate extends Human {
#Override
public int getLegsNumber() { return 1; }
public int getWoodLegNumber() { return 1; }
}
class Dog implements Mammal {
#Override
public void accept(MamalVisitor visitor) { visitor.visit(this); }
#Override
public int getLegsNumber() { return 4; }
}
///////////////////////////////////
///////////////////////////////////
class LegCounterVisitor implements MamalVisitor {
private int legNumber = 0;
#Override
public void visit(Mammal mammal) { legNumber += mammal.getLegsNumber(); }
public int getLegNumber() { return legNumber; }
}
class WoodLegCounterVisitor implements MamalVisitor {
private int woodLegNumber = 0;
#Override
public void visit(Mammal mammal) {
// perhaps bad but i'm lazy
if ( mammal instanceof Pirate ) {
woodLegNumber += ((Pirate) mammal).getWoodLegNumber();
}
}
public int getWoodLegNumber() { return woodLegNumber; }
}
///////////////////////////////////
///////////////////////////////////
public class Main {
public static void main(String[] args) {
// Create a list with 9 mammal legs and 3 pirate woodlegs
List<Mammal> mammalList = Arrays.asList(
new Pirate(),
new Dog(),
new Human(),
new Pirate(),
new Pirate()
);
///////////////////////////////////
// The visitor method
LegCounterVisitor legCounterVisitor = new LegCounterVisitor();
WoodLegCounterVisitor woodLegCounterVisitor = new WoodLegCounterVisitor();
for ( Mammal mammal : mammalList ) {
mammal.accept(legCounterVisitor);
mammal.accept(woodLegCounterVisitor);
// why not also using:
// legCounterVisitor.visit(mammal);
// woodLegCounterVisitor.visit(mammal);
}
System.out.println("Number of legs:" + legCounterVisitor.getLegNumber());
System.out.println("Number of wood legs:" + woodLegCounterVisitor.getWoodLegNumber());
///////////////////////////////////
// The standart method
int legNumber = 0;
int woodLegNumber = 0;
for ( Mammal mammal : mammalList ) {
legNumber += mammal.getLegsNumber();
// perhaps bad but i'm lazy
if ( mammal instanceof Pirate ) {
woodLegNumber += ((Pirate) mammal).getWoodLegNumber();
}
}
System.out.println("Number of legs:" + legNumber);
System.out.println("Number of wood legs:" + woodLegNumber);
}
}
///////////////////////////////////
I just wonder what is the main advantage for this case to use such a pattern. We can also iterate over the collection and get almost the same thing, except we don't have to handle a new interface and add boilerplate code to the model...
With Apache Commons, or a functional language, the classic way seems to do some map/reduce operation (map to the leg numbers and reduce with addition) and it's quite easy...
I also wonder why we use
mammal.accept(legCounterVisitor);
mammal.accept(woodLegCounterVisitor);
and not
legCounterVisitor.visit(mammal);
woodLegCounterVisitor.visit(mammal);
The 2nd option seems to remove the accept(...) method on the model part.
In many samples i've found, it seems that they don't use a common interface for model objects. I added it because like that i just have to add one visit(Mammal) method, instead of implementing one for each Mammal.
Is it good to make all my objects implement Mammal? (i guess sometimes it's just not possible anyway). Is it still a Visitor pattern like that?
So my questions are:
- do you see any advantage in my exemple for using visitors?
- if not, can you provide some concrete usecases for visitors?
- are visitors useful in functional programming languages
The only exemple that i found relevant for this pattern is the case of a pretty printer, where you keep in the visitor's state the offset to use during the visit of different nodes (for displaying an XML tree for exemple)
The visitor pattern is just double dispatch.
I'm not sure I agree with your implementation of a visitor. I'd implement something like this:
interface MammalVisitor {
void visit(Pirate pirate);
void visit(Human human);
void visit(Dog dog);
}
// Basic visitor provides no-op behaviour for everything.
abstract class MammalAdapter implements MammalVisitor {
void visit(Pirate pirate) {};
void visit(Human human) {};
void visit(Dog dog) {};
}
And then the implementation would become cleaner:
// We only want to provide specific behaviour for pirates
class WoodLegCounterVisitor extends MammalAdaptor {
private int woodLegNumber = 0;
#Override
public void visit(Pirate pirate) {
woodLegNumber += pirate.getWoodLegNumber();
}
public int getWoodLegNumber() { return woodLegNumber; }
}
In answer to your actual question, the main advantage of using the visitor is avoiding the need to do the "instanceof" checks. It gives you the ability to separate out the logic for processing a hierarchy into a separate class. It also gives you the ability to add new behaviour without changing the original classes.
Visitor pattern is a fancy switch case / pattern matching system to facilitate graph traversal.
As typical functional languages offer pattern matching and efficient ways to traverse graphs, interest is much more limited.
Even in JAVA, with instanceof or using enum, a visitor is more of a fancy way to perform things than a generic solution as many algorithms will not fit well into it.
The purpose of the Visitor Pattern is to separate the object structure (in your case, Mammal) from the algorithm (in your case, the counter Leg counter algorithm).
The whole idea is that your object (mostly in java, JavaBeans) doesn't change its structure at all, and only a new virtual function is introduced to introduce a new algorithm.
Unlike Jeff Foster's implementation, One can use Generics to make code easier. This brings specificity to your visitor, e.g.:
public interface MammalVisitor<T extends Mammal> {
public void visit(T mammal);
}
public class LegCounterVisitor implements MamalVisitor<Human> {
private int legNumber = 0;
#Override
public void visit(Human mammal) { legNumber += mammal.getLegsNumber(); }
public int getLegNumber() { return legNumber; }
}
public class WoodLegCounterVisitor implements MamalVisitor<Pirate> {
private int legNumber = 0;
#Override
public void visit(Pirate mammal) {legNumber += mammal.getWoodLegNumber(); }
public int getLegNumber() { return legNumber; }
}
Related
For example, for a game I have some Skill, which is data object:
public interface Skill{
public String getName();
}
public class Attack implements Skill{
public String getName(){ return "Attack"; }
public int power;
}
public class Speak implements Skill{
public String getName(){ return "Speak"; }
public String speech;
}
To apply the skills during the game, I need some SkillHandler for each corresponding skill:
public interface SkillHandler{
public void apply(Skill skill);
}
public class AttackHandler{
#Override
public void apply(Skill skill){
Attack attack=(Attack)skill;
Player player=Global.getPlayer();
Enemy enemy=Global.getEnemy();
enemy.hp=enemy.hp-attack.power;
//some other code for follow up handle
}
}
public class SpeakHandler{
#Override
public void apply(Skill skill){
Speak speak=(Speak)skill;
Label label=new Label(speech);
this.displayOnTop(label);
}
}
I use one SkillHandler for each Skill because I don't want the Skill depend on SkillHandler, and PlayerAttackStateHandler would apply each skill:
public class PlayerAttackStateHandler{
public PlayerAttackHandler(){
Skill[] skills=Global.getSkills();
for(int i=0;i<skills.length;i++){
SkillHandler skillHandler=null;
if(skills[i].getName().equals("Attack")){
skillHandler=new AttackHandler();
}else if(skills[i].getName().equals("Speak")){
skillHandler=new SpeakHandler();
}
skillHandler.apply(skills[i]);
}
}
}
I know this design is ill-formed because it has at least 2 problems:
I need to update the long if-else chain if a new Skill as well as new SkillHandler is added, which seems does't follow open-closed principle
it has a dynamic cast in each SkillHandler
My question is, is there any design pattern to eliminate both if-else and dynamic cast (if possible) in this case, while keep the Skill not depend on SkillHandler?
It seems that your implementation has lot in common with visitor pattern, something like this:
public interface ISkillable //this is your Skill
{
public int GetPower();
public string GetSpeak();
}
public interface IVisitable //player or npc
{
public void Accept(IVisitor visitor)
}
public interface IVisitor //AttackHandler or SpeakHandler
{
public void ApplySkill(ISkillable skillable)
}
public class Player implements ISkillable, IVisitable
{
...
public void Accept(IVisitor visitor)
{
visitor.Visit(this);
}
}
public class AttackVisitor implements IVisitor
{
public void Visit(ISkillable skillable)
{
//do something with power
}
}
and then example how it can be used is
player.Accept(new AttackVisitor(/*you can provide additional info like enemy*/));
player.Accept(new SpeakVisitor());
See Attack and Speak as capabilities some agent could possess.
I would consider testing capabilities/features:
interface Attacking { void attack(); }
interface Speaking { void speak(); }
Animal animal = ...
Optional<Attacking> attacker = animal.lookup(Attacking.class);
attacker.ifPresent(a -> a.attack());
Optional<Speaking> speaker = animal.lookup(Speaking.class);
speaker.ifPresent(sp -> sp.speak());
Animal need not implement any interface, but you can look up (lookup or maybe as) capabilities. This is extendible in the future, dynamic: can change at run-time.
Implementation as
private Map<Class<?>, ?> map = new HashMap<>();
public <T> Optional<T> lookup(Class<T> type) {
Object instance = map.get(type);
if (instance == null) {
return Optional.empty();
}
return Optional.of(type.cast(instance));
}
<S> void register(Class<S> type, S instance) {
map.put(type, instance);
}
The implementation does a safe dynamic cast, as register ensures the safe filling of (key, value) entries.
I wrote an abstract superclass distribution as folows, it contains a constructor, and two methods.
public abstract class Distribution
{
public Distribution(){}
public abstract void setParameters(HashMap<String,?> hm);
public abstract int getSample();
}
Hereafter, I wrote 4 subclasses ( Poisson, Geometric, Deterministic and Binomial ). These subclasses all look the same and are like this;
public class Binomial extends Distribution
{
BinomialDistribution distribution;
public Binomial()
{
super();
}
#Override
public void setParameters(HashMap<String,?> hm)
{
try
{
int n = 0;
double p =0.0;
if (hm.containsKey("n"))
if (hm.containsKey("p"))
p = Double.parseDouble((String) hm.get("p"));
else
throw new Exception("Exception: No p-value found");
else
throw new Exception("Exception: No n-value found");
distribution = new BinomialDistribution(n,p);
}
catch(Exception e)
{
System.out.println(e.getMessage());
}
}
#Override
public int getSample()
{
return distribution.sample();
}
}
In another class I want to use these classes. I want to give a HashMap to the Distribution.setparameters method, and let the program decide which subclass that fits the parameters given in that HashMap.
If I want to define A distribution the other class, this doesn't seem to work.
Distribution arrivalLength1distr = new Distribution();
Can somebody tell me what I do wrong and how my problem could be solved ?
Thanks !
Hello I want to do a really simple thing. Just make a template function for any numbers. I actually want as little as ability to "add". In C++ it would be really trivial like this:
template <typename T>
inline T add (T a, T b) {
return a + b;
}
int main(int argc, char** argv){
printf("int: %d\n",add(1,2));
printf("float: %f\n",add(1.1,2.1));
}
In Java I got a tough lesson. I'm new to Java so I believe (and hope) I'm totally wrong and over engineering this. But only thing I come up with was:
public interface IntrfcWowNumbersAdds<T> {
T add(Number v);
}
public class SuperSmartInteger extends Number implements IntrfcWowNumbersAdds<SuperSmartInteger>{
private Integer i;
public SuperSmartInteger(int v) {
i = v;
}
#Override
public String toString(){
return ""+i;
}
#Override
public SuperSmartInteger add(Number v) {
return new SuperSmartInteger(this.intValue()+v.intValue());
}
#Override
public int intValue() {
return i; // thx god for auto(un)boxing
}
#Override
public long longValue() {
return i;
}
#Override
public float floatValue() {
return i;
}
#Override
public double doubleValue() {
return i;
}
}
And note that this crazy wrapper above I would have to do for any number I would like to use template for (eg double, byte etc...)
public class ThreadSafeNum<T extends Number & IntrfcWowNumbersAdds<T>> {
private T num;
public ThreadSafeNum(T n){
num = n;
}
public T add(T v){
// note in here I plan to do some locking...
return num = num.add(v);
}
}
then I can use it as:
SuperSmartInteger i = new SuperSmartInteger(5);
SuperSmartInteger i2 = i.add(6);
System.out.println(""+i2);
ThreadSafeNum<SuperSmartInteger> tsn = new ThreadSafeNum<SuperSmartInteger>(i);
SuperSmartInteger i3 = tsn.add(i2);
I know that when add() would be only adding I can just use + operator and rely on auto(un)boxing. But my add() method is meant to do something extra (like lock).
So how to do it properly? Or is my way correct???
Something like this as the base class:
public abstract class Addable<T extends Number,U extends Addable<T,U>> {
private final T value;
public Addable( final T value ){ this.value = value; }
public T getValue(){ return value; }
public abstract U add( U addend );
}
And this as the sub-class:
public class AddableInteger extends Addable<Integer,AddableInteger> {
public AddableInteger( final Integer value ){
super( value );
}
#Override
public AddableInteger add( final AddableInteger addend ){
java.util.Objects.requireNonNull( addend );
return new AddableInteger( this.getValue() + addend.getValue() );
}
}
Well, the reasons that works in C++ is that the compiler will create as many functions as there are calls in the code, and compile each one independently in order to validate if '+' is a reasonable thing to do in that particular case. This is a little like a case of compiler-assisted duck-typing. In other words, there is no guarantee that type T will have a + operator and only the fact that the compiler will look at the actual call types and create permutations helps you.
Note that there is some risk in letting the compiler "add whatever", since there is no interface or contract that guarantees the semantics to be correct. That is what a class hierarchy brings you.
This is trickier to do in full type safety since inheritance can be complex and the return types need to be somewhat clear. Inheritance is the usual thing so that a virtual method knows how to add its own type, but in this case you can't change the class hierarchy of Number.
You can, nevertheless, do something like this:
public static int addAsInt(Number a, Number b)
{
a.intValue() + b.intValue();
}
And the same for other return types. That will take any two instances of number and generate an output value, assuming which kind of output type you want. Somewhat easier than creating wrapper classes in this particular case.
let's imagine the following situation: I want to design a bidding application (like ebay) with the composite design pattern
I create an abstract superclass like "BidComponent" (which has getName()) and two subclasses "Article" and "Category".
Category has a List which can contain other BidComponents, Article does not implement a List but a getPrice() method.
If I want to iterate through this structure and I want to print out the Category-Article-Structure I need instanceof:
if(element instanceof Article){
Article article = (Article)element;
System.out.println(article.getName() + ":" + article.getPrice());
}else{
Category category = (Category)element;
System.out.println(category.getName());
}
This seems pretty wrong to me. Is there a better way to realise this (So without always checking the type via instanceof)? I ask this question because I read several times that using instanceof is bad design...
//Edit to mention my problem with Visitors:
Ok. But let's imagine I want to search the highest bid to all products. So I have
public class HighestBidVisitor implements BidComponentVisitor{
private double highestBid = 0d;
public HighestBidVisitor(Category category){
visitCategory(category);
}
#Override
public void visitCategory(Category category){
Iterator<BidComponent> elementsIterator = category.iterator();
while(elementsIterator.hasNext()){
BidComponent bidComponent = elementsIterator.next();
//Now I have again the problem: I have to check if a component in the Categorylist is an article or a category
if(bidComponent instanceof Article) visitArticle((Article)bidComponent);
else visitCategory((Category)bidComponent);
}
}
#Override
public void visitArticle(Article article){
if(article.getPrice() > highestBid) highestBid = article.getPrice();
}
}
But now I have the same problem again (See comment in visitCategory). Or am I doing this wrong?
You want to use the visitor pattern.
public interface BidComponentVisitor {
void visitArticle(Article article);
void visitCategory(Category category);
}
Then your BidComponent class would have a visit method:
public abstract void visitChildren(BidComponentVisitor visitor);
The Composite and Visitor patterns often work together.
Edit: The key to avoiding instanceof when using the vistor pattern is how you implement the visitChildren method. In Category you would implement it like this:
#Override
public void visitChildren(BidComponentVisitor visitor) {
vistor.visitCategory(this);
for (BidComponent child : children) {
child.visitChidren(visitor);
}
}
Since Article has no children, it's implementation is simpler:
#Override
public void visitChildren(BidComponentVisitor visitor) {
vistor.visitArticle(this);
}
They key is each concrete class in the composite pattern knows it's own type, so it can call the specific visitor method that has a parameter with it's specific type.
One variation is to have enter and exit methods in the visitor for any class with children:
public interface BidComponentVisitor {
void visitArticle(Article article);
void enterCategory(Category category);
void exitCategory(Category category);
}
With the above interface, Category.visitChildren() would look like this:
#Override
public void visitChildren(BidComponentVisitor visitor) {
vistor.enterCategory(this);
for (BidComponent child : children) {
child.visitChidren(visitor);
}
vistor.exitCategory(this);
}
To print the tree, you could do something like this:
public class PrintingVisitor implements BidComponentVisitor {
private int depth = 0;
private void printIndent() {
for (int i = 0; i < depth; i++) {
System.out.print(" ");
}
}
public void visitArticle(Article article) {
printIndent();
System.out.println(article.toString());
}
public void enterCategory(Category category);
printIndent();
System.out.println(category.toString());
depth++;
}
public void exitCategory(Category category) {
depth--;
}
}
The disadvantage of the visitor patter is your visitor class needs to either hardcode every possible subclass, or have a generic visitOther() method.
You are doing the visitor implementation wrong. The different Components handle their own dispatching of elements. They know what type they are so you don't need to do any instanceof checks.
public interface Visitor{
void visit(Article a);
void visit(Category c);
}
abstract class BidComponent{
...
abstract void accept(Visitor v);
}
public class Category{
....
public void accept(Visitor v){
v.visit(this); // visit Category
for(Article a : getArticles()){
v.visit(a); //visit each article
}
}
}
Then a visitor to find the highest bid
public class HigestBidVisitor implements Visitor{
private final double highest;
void visit(Category c){
//no-op don't care
//or we could track which Category we have visited last
//to keep track of highest bid per category etc
}
void visit(Article a){
highest= Math.max(highest, a.getPrice());
}
}
Then to search all:
HigestBidVisitor visitor = new HighestBidVisitor();
BidComponent root = ...
root.accept(visitor);
double highest = visitor.getHighestPrice();
I can't think of any clean solution right now. You might have to update your implementation to either store Article and Category instances separately.
With your current implementation where a List<BidComponent> needs to be traversed and each element needs to be processed based on it's type, this approach can be a bit better:
abstract class BidComponent {
public abstract String process();
}
class Category extends BidComponent {
#Override
public String process() {
return getName();
}
}
class Article extends BidComponent {
#Override
public String process() {
return getName() + " " + getPrice();
}
}
List<BidComponent> list = ..;
for (BidComponent c : list) {
System.out.println(c.process());
}
Another way to decouple the processing logic from the classes/objects is:
Map<Class<?>, Function<BidComponent, String>> processors = new HashMap<>();
processors.put(Category.class, Category::getName());
processors.put(Article.class, a -> a.getName() + " " + a.getPrice());
List<BidComponent> list = ..;
for (BidComponent c : list) {
System.out.println(processors.get(c.getClass()).apply(c));
}
Note that this uses Java 8 lambdas but the same can be implemented with Java 7 or lower by using your own interface (similar to Function) or the ones provided by Guava or Apache Commons.
[edit] Hmm, clearly I'm not asking this properly. Could you tell me why this is a bad question?
To put this differently, I want to find a why to implement what is define in this article as "Pure object aggregation" instead of "Object organized as a blob".
I'm doing my first attempt at implementing the aggregation pattern in Java.
At first glance Interfaces seems to be the answer, I ran into confusion when I needed default values for attributes.
Since constants are static, if I define anything in the interface it will be shared with every class that implements it. What I was going for was that I only need to implement this in cases when I wanted a value different from default.
Here an abstract class seems a better fit but I fall back to a multiple inheritance problem.
Here is the (impossible) skeleton I can up with:
public interface MenuItemPopup {
// Defaults
int windowHeight = 200;
int windowWidth = 350;
public void open();
public void setWindowHeight(int newHeight){
windowHeight = newHeight;
}
public void setWindowWidth(int newWidth){
windowWidth = newWidth;
}
}
public interface WindowButton {
// Defaults
Point size = new Point (5, 120);
public void initialize();
public void setSize(Point newSize){
size = newSize;
}
}
public class SomeFuncGUI extends MandatoryParentClass implements WindowButton, MenuItemPopup{
public void open(){
// do stuff
}
public void initialize(){
// do more stuff
}
}
public class OtherFuncGUI extends MandatoryParentClass implements MenuItemPopup{
public OtherFuncGUI(Point customPosition){
setSize(new Point(45, 92));
}
public void open(){
// do stuff
}
}
public class MainClass{
ArrayList <MandatoryParentClass> list = new ArrayList <MandatoryParentClass>();
list.add(new SomeFuncGUI());
list.add(new OtherFuncGUI());
for( MandatoryParentClass button : list){
// process buttons
if(button instanceof WindowButton){
button.open();
}
// process popups
if(button instanceof MenuItemPopup){
button.initialize();
}
}
}
I realise this doesn't compile.
How would I change this to implement aggregation pattern for MenuItemPopup and WindowButton?