menu

Wednesday, October 15, 2014

Reflective Visitor Design Pattern

Reflective Visitor Design PatternIntroduction:

     Today we talk about Visitor design pattern which is one of the behavioral design patterns.We point out which basic problem can be solved by this pattern and see how it can be improved to use with reflection for a more elastic solution.
The visitor design pattern is used when there are different value typed objects in a collection and we need similar operation to do on these objects. The UML graphic can be seen in Figure 1.


Reflective Visitor Design Pattern

                                                                    Figure 1

Implementation:

Lets first work on a collection that include different objects without visitor pattern.

        List heterogenList = new ArrayList();

        heterogenList.add("A");
        heterogenList.add(1);
        heterogenList.add(Calendar.getInstance());

        for (Iterator iterator = heterogenList.iterator(); iterator.hasNext();) {
            Object heterogenElement = (Object) iterator.next();
            if (heterogenElement instanceof String) {
                String myString = (String) heterogenElement;
                System.out.println("myString:" + myString);
                //do sth with the value
            }
            else if (heterogenElement instanceof Integer) {
                Integer myInteger = (Integer) heterogenElement;
                System.out.println("myInteger:" + myInteger);
                //do sth with the value
            }
            else if (heterogenElement instanceof Calendar) {
                Calendar myCalendar = (Calendar) heterogenElement;
                System.out.println("myCalendar:" + myCalendar);
                //do sth with the value
            }
        }

As can be seen to read the different objects from the collection we need to use instanceof keyword in the loop.That means if we add a different typed object to our collection, we need to add a new if statement to our source code. If we are continuosly using if keyword in our code, it shows that we do some mistake and we have to revise our design.Instead of if, we can use abstraction to obtain more elastic, tracable and maintainable software.In addition, changing an already tested code after each new type added to our collection is against the open-closed design principle and is a situation that we have to escape. In this case the visitor design pattern comes to rescue.
Lets first define the interfaces and classes that we need.

//Visitor interface
public interface Visitor {
   void visit(WrappedString wString);
   void visit(WrappedCalendar wCalendar);
   void visit(WrappedInteger wInteger);
}
//The interface of the object that will be visited
public interface Element {
    void accept(Visitor visitor);
}
//The objects that will be used in the list to visit
public class WrappedString implements Element {
    private String name;
    private String wString;
    public WrappedString(String name, String wString) {
        this.name = name;
        this.wString = wString;
    }
    public String getName() {
        return name;
    }
    public String getwString() {
        return wString;
    }
    @Override
    public void accept(Visitor visitor) {
        visitor.visit(this);
    }
}

public class WrappedInteger implements Element {
    private String name;
    private int wInt;
    public WrappedInteger(String name, int wInt) {
        this.name = name;
        this.wInt = wInt;
    }
    public String getName() {
        return name;
    }
    public int getwInt() {
        return wInt;
    }
    @Override
    public void accept(Visitor visitor) {
        visitor.visit(this);
    }
}

import java.util.Calendar;

public class WrappedCalendar implements Element{
    private Calendar wCalendar;
    private String name;
    public WrappedCalendar(String name, Calendar wCalendar) {
        this.name = name;
        this.wCalendar = wCalendar;
    }

    public Calendar getWCalendar() {
        return wCalendar;
    }

    public String getName() {
        return name;
    }
    @Override
    public void accept(Visitor visitor) {
        visitor.visit(this);
    }
}

//Concrete Visitor
public class ConcreteVisitor implements Visitor {
    @Override
    public void visit(WrappedString wString) {
        System.out.println(wString.getName());
        // do sth
    }
    @Override
    public void visit(WrappedCalendar wCalendar) {
        System.out.println(wCalendar.getName() + "-" + wCalendar.getWCalendar().getTimeInMillis());
        // do sth
    }
    @Override
    public void visit(WrappedInteger wInteger) {
        System.out.println(wInteger.getName() + "-" + wInteger.getwInt());
        // do sth
    }
}

Now lets rewrite the previous example with visitor design pattern.

       List heterogenList = new ArrayList();

        heterogenList.add(new WrappedString("wString","A"));
        heterogenList.add(new WrappedInteger("wInteger", 1));
        heterogenList.add(new WrappedCalendar("wCalendar", Calendar.getInstance()));

         Visitor visitor = new ConcreteVisitor();
         //Visitor visitor = new AnotherConcreteVisitor();
         for (Iterator iterator = heterogenList.iterator(); iterator.hasNext();) {
            Element element = (Element) iterator.next();
            element.accept(visitor);
        }

Now we get rid of the instanceof keyword.Since all the objects in the collection are implements the Element interface , the only thing we have to do is to read the Element interface from the list and call the accept method with a visitor object.Each of the objects in the list, will pass itself to the visit method of the visitor in its accept method, and in the visitor object the business logic related with the object will be done.The important point here is, the ability to add new visitors with new business logics on the objects without affecting the client code. 

Reflective Visitor Design Pattern Implementation:

The visitor design pattern behaves quite elastic adding new visitors, however when we want to add new object to the collection, it requires to change the Visitor interface.In java and all of other object oriented languages, changing an interface after its published is one of the most problematic thing, because when the interface is changed, all of the classes that implement that interface has to be changed.To solve this issue, we can build the visitor interface by reflection.
The reflected interface will be like below.

//Reflective Visitor interface
public interface ReflectiveVisitor {
   void visit(Object o);
}
//Reflective Element
public interface ReflectiveElement {
    void accept(ReflectiveVisitor visitor);
}
//The new object to visit (We change WrappedString class as to implement //ReflectiveElement 
public class WrappedDouble implements ReflectiveElement {
    private String name;
    private double wDouble;
    public WrappedDouble(String name, double wDouble) {
        this.name = name;
        this.wDouble = wDouble;
    }
    public String getName() {
        return name;
    }
    public double getWDouble() {
        return wDouble;
    }
    @Override
    public void accept(ReflectiveVisitor visitor) {
        visitor.visit(this);
    }
}
public class WrappedString implements ReflectiveElement {
    private String name;
    private String wString;
    public WrappedString(String name, String wString) {
        this.name = name;
        this.wString = wString;
    }
    public String getName() {
        return name;
    }
    public String getwString() {
        return wString;
    }
    @Override
    public void accept(ReflectiveVisitor visitor) {
       visitor.visit(this);
    }
    @Override
    public String toString() {
        return name + "-" + wString;
    }
}
//Reflective Concrete Visitor
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

public class AnotherConcreteVisitor implements ReflectiveVisitor {
    @Override
    public void visit(Object o) {
        try {
            Method visitMethod = this.getClass().getMethod("visit", new Class[] { o.getClass() });
            if (visitMethod == null) {
                defaultVisit(o);
            } else {
                visitMethod.invoke(this, new Object[] { o });
            }
        } catch (NoSuchMethodException e) {
            this.defaultVisit(o);
        } catch (InvocationTargetException e) {
            this.defaultVisit(o);
        } catch (IllegalAccessException e) {
            this.defaultVisit(o);
        }
    }
    public void defaultVisit(Object o) {
        System.out.println(o.toString());
    }
    public void visit(WrappedDouble wDouble){
        System.out.println(wDouble.getName() + "-" + wDouble.getWDouble());
        // do sth
    }
}

Lets rewrite the previous example again,

        List heterogenList = new ArrayList();

        heterogenList.add(new WrappedString("wString","A"));//default visit method
        heterogenList.add(new WrappedDouble("wDouble", 1.0));

         ReflectiveVisitor visitor = new AnotherConcreteVisitor();
         for (Iterator iterator = heterogenList.iterator(); iterator.hasNext();) {
            ReflectiveElement reflectiveElement =  (ReflectiveElement) iterator.next();
            reflectiveElement.accept(visitor);
        } 

In this approach, all the objects in our collection are calling the generic visit method of visitor class.
This generic visit method takes Object as parameter, and depending on the type of parameter, calls the related visit method.The important point is, the visitor class has to define visit(data:DataType) method for all data types that it wants to play.If the related visit method cannot be found, there can be a defaultVisit method to do a generic default job.

Conclusion:

     With reflective visitor design pattern, the elasticity of adding new visitors is to be improved to include adding new objects to the collection.When we need to add new object to the already defined visitor, all we need is to add a visit method for the new objects to the visitor class.We don't need to change the ReflectiveInterface interface and other visitors.
However this elasticity comes with a performance loss.Since the method that will be called by reflection determined at runtime dynamically, some JVM optimization cannot be done and so reflected parts can cause very bad performance especially at hot spots.
When we execute the below example in my machine using reflection and without using reflection with 1000000 objects we get 50 times slower results.In addition when we increase the number of objects to 10000000 we get Out of Memory error.
The reason may because of the heap space or perm gen space depending on the situation.If you use heavy reflection then it may the JVM's mechanism called "inflation" to run the reflected method faster causes the Out of Memory error with perm gen.Normally, up to a defined calling number, creating an instance of MethodAccessor which is an inner class defined in Method class, each invoke call send to the MethodAccessor's invoke method by JNI (Java Native Interface). Since the JNI method call is very slow, after some method calls, JVM creates a new class at runtime.This class also include invoke method , the instance of it will be used for the invoke calls instead of JNI calls. This technique is called as inflation, and the performance problem of reflection minimized using this.However even with this improvement we still have 50 times slower results.
The classes and the references of instances of this class are kept in permanent generation part of heap.(In our case only one instance of the class created) (Permanent generation hold  class and method definitions, constant pool information (taken from class file), references of object arrays and type arrays associated with the class, classes created at runtime by JVM by inflation, references of static variables, and the information used by JIT for optimization.)
When there is huge amount of reflected method calls with different objects, the classes created for inflation by JVM may cause to fill the permanent generation causing Out of Memory.
In this case you have to reserve enough memory for permanent generation to be used by JVM.

References and Resources:

Erich Gamma, Richard Helm, Ralph Johnson, John Vlissides. Desing Patterns -  Elements of Reusable Object-Oriented Software

http://anshuiitk.blogspot.com/2010/11/excessive-full-garbage-collection.html

You can download the source code from here.

30 comments:

  1. It's not an easy time to be graduating from college with student loans. With the unemployment rate soaring toward 10 percent and the average starting salary for college graduates down 2.2 percent this year, student loan borrowers - whose average debt from student loans tops $22,000 - are now having an even tougher time affording their student loan payments. buymodafinilonline.reviews

    ReplyDelete
  2. Any business, whether small or big, faces many challenges and some of the biggest challenges are in the shape of disasters, especially the natural ones. It does not matter which part of the world your business operates in; natural disasters are possible in every part of the planet. 3d coat latest version

    ReplyDelete
  3. use it for a large group of other "off mark" reasons. It just continues showing signs of improvement! buy modvigil in usa

    ReplyDelete
  4. dj equipments that are built by Sennheiser are the best in my opinion, we always use them when we have a gig:: putlocker

    ReplyDelete
  5. The thing that matters was opportunity. Those that fizzled couldn't discover the chance to build up an important development utilizing their technology. best microphone for streaming

    ReplyDelete
  6. When we lose our ability and the opportunity for emotional connectedness, toronto condos we are in danger of becoming as inanimate as the technology we so greatly desire.

    ReplyDelete
  7. In this competitive world, the latest technology services are available to small and medium-sized businesses, once only available to multinational companies. combination weigher

    ReplyDelete
  8. This comment has been removed by the author.

    ReplyDelete
  9. There are three groups on which the versatile transmission depends on, with various nations working on an alternate recurrence falling under various groups. Today, quad band cell phones remove the dread in you, calming you from that stress, if your cell phone will work in UK. Dumps cvv

    ReplyDelete
  10. There were additionally worries of grant allotments, problematic enlisting strategies and understudy competitor treatment that prompted Tech's takeoff from the SEC.why you should always use a vpn

    ReplyDelete
  11. This can help tech support a ton in the event that they can get the model number of the PC, printer, and so on you are attempting to get tech support for. túlméretes szállítás Europa-Road Kft.

    ReplyDelete
  12. On the off chance that a craftsman is attempting to impart something, the sound tech ought to be focusing on that as well. IT consulting services Brampton

    ReplyDelete
  13. She has a more youthful sibling who additionally utilizes the PC to finish his school work so she subsequently needs to keep awake until late to finish tasks. She states "technology and I? We never had that association" (Lohnes). power electronic

    ReplyDelete
  14. Assuming you continue to get this message and can't interface, it might show that the Contivity VPN Switch can't speak with the customer since it is behind some sort of NAT (Network Address Translation) gadget. free vpn for netflix

    ReplyDelete
  15. An absence of openness could broaden the advanced separation - that is, the hole between those with and without admittance to computerized technology - and restrict a few youngsters' school preparation and early achievement. solar

    ReplyDelete
  16. In addition to the fact that it spawned new ventures and items, yet it brought forth other progressive advancements - semiconductor technology, incorporated circuit technology, Best Free Wordpress Themes

    ReplyDelete
  17. Then again, assuming you are overwhelmed with mice, the chance exists to develop an item utilizing your technology. Clicks Test

    ReplyDelete
  18. Then again, the article "What Screenagers Say About... " High young understudies were gotten some information about their opinion about technology yet most communicated loving it. EMF Protection

    ReplyDelete
  19. In addition to the fact that it spawned new businesses and items, yet it generated other progressive innovations - semiconductor technology, incorporated circuit technology, microchip technology. digital signature services

    ReplyDelete
  20. The intricacy of the mechanical world is brilliant however similarly as confusing, and hard to get a handle on. However, the analysts, specialists, and experts definitely need to zero in on their own part of the work.https://onohosting.com/

    ReplyDelete
  21. Our definition doesn't endeavor to negate current definitions. All things considered, we view from an alternate point, zeroing in on a more profound level, arranging on the text-focused model of the world. https://hostinglelo.in/

    ReplyDelete
  22. By 1917, with the beginning of WWI, UGA disbanded its football program since a significant number of its capable bodies understudies were selected for the conflict. Since Atlanta was a tactical preparing ground at that point, Qualtech Security

    ReplyDelete
  23. Strategies, abilities, materials, methods, standards, etc, all should be reported for getting, learning, correspondence, and recording purposes. Client manuals, technical particulars are normally the principal stuff required by clients and specialists, Concise Finance London Retirement Mortgage

    ReplyDelete
  24. As to fundamental nature of and contrasts among science and technology, presently we give another meaning of technology as:how to watch tv on laptop

    ReplyDelete
  25. zeroing in on determining hypotheses, these messages are more with regards to science. On the off chance that the intention is in the text to non-text bearing, zeroing in on making a move, these texts are more with regards to technology. cheap hosting plans

    ReplyDelete
  26. i never know the use of adobe shadow until i saw this post. thank you for this! this is very helpful. Satta 786

    ReplyDelete
  27. What were you doing at that point? These are a few things I could ask the individual requesting my tech support. https://www.buyyoutubesubscribers.in/

    ReplyDelete
  28. For aluminum, stainless, titanium or thin sheets, heat control is key. No process controls heat and produces fine welds like a Best TIG Welder Under 800$. Whether you call it TIG, Heli-Arc or GTAW, this process is top of the line. This two-handed method is also the most rewarding to master. A TIG machine carries quite a price if you’re unsure what you really need.

    ReplyDelete
  29. If you have a musculoskeletal injury or movement dysfunction, your healthcare provider may refer you to physical therapy to help decrease pain and improve mobility. Your symptoms may be mild, or you may have symptoms that severely limit your functional mobility.Find out more about how these physical therapy service treatments are used in the field.

    ReplyDelete
  30. "You are so intriguing! I figure I haven't really scrutinized anything equivalent already.
    It's uncommon to find someone who has a certified idea on this point.
    Genuinely, thank you for starting this.찰떡궁합출장샵추천
    광주출장샵추천
    대전출장샵추천
    대구출장샵추천
    부산출장샵추천
    울산출장샵추천
    서울출장샵추천

    ReplyDelete