Sunday, January 8, 2017

Ditch Visitor Pattern for A Better Solution

You could just ditch Visitor Pattern as there is a better solution for Java.

The pitfall of Visitor Pattern:

It is intrusive, and anti-pattern

The visitor pattern use double-dispatch, that usually goes like this:
public class ParentDataModel
{
    public void accept(Visitor visitor)
    {
        visitor.visit(this);
    }
}

public class ChildDataModel extends ParentDataModel 
{
    // no need to implement accept() by the child itself
}

public class Visitor 
{
    public void visit(ParentDataModel model)
    {
        // do something with it
    }

    public void visit(ChildDataModel model)
    {
        // do something with it
    }
}
Why on earth a data model need to be aware of visitor? A data model should only hold the data relevant to the model.

Does not go well with existing objects from external frameworks

What if you need to do something with, say Number, Double, that are from the JDK.
Even say you're willing to make a wrapper around each object you need in your project, it's hell tedious, and think about how many classes you will have to refactor to get this to work.
public class NumberWrapper 
{
    private Number value;

    public void accept(Visitor visitor)
    {
        visitor.visit(value);
    }
}

public class DoubleWrapper 
{
    private Double value;

    public void accept(Visitor visitor)
    {
        visitor.visit(value);
    }
}

public class Visitor 
{
    public void visit(Number value)
    {
        // do something with it
    }

    public void visit(Double value)
    {
        // do something with it
    }
}

Solution: One class rules them all

public static class SuperConsumer implements Consumer
{
    private Map<Class, Consumer> consumers = new HashMap<>();
    private Consumer unknown = o -> System.err.println("Unknown object type");

    public SuperConsumer()
    {
        consumers.put(Number.class, o -> consumeNumber(o));
        consumers.put(Double.class, o -> consumeDouble(o));
    }

    private void consumeNumber(Number value)
    {
         System.out.printf("Consuming: %s\n", value.getClass().getName());
    }

    private void consumeDouble(Double value)
    {
         System.out.printf("Consuming: %s\n", value.getClass().getName());
    }

    private Consumer findConsumer(Object object)
    {
        Consumer consumer = consumers.get(object.getClass());

        Class superClazz = object.getClass().getSuperclass();
        while (consumer == null && superClazz != Object.class)
        {
            consumer = consumers.get(superClazz);
            superClazz = superClazz.getSuperclass();
        }

        Class[] interfaces = object.getClass().getInterfaces();
        for (int i = 0; consumer == null && i < interfaces.length; i++)
        {
            consumer = consumers.get(interfaces[i]);
        }

        return consumer;
    }

    @Override
    public void accept(Object object)
    {
        Consumer consumer = findConsumer(object);
        if (consumer == null)
        {
            consumer = unknown;
        }
        consumer.accept(object);
    }

    public static void main(String[] args)
    {
        Consumer consumer = new SuperConsumer();
        Arrays.asList(new Double(1.0), new Integer(1), new Float(1.0f)).forEach(o -> consumer.accept(o));
    }
}

Copied from my answer on StackOverflow to question: Generified implementation of Visitor pattern in Java

Monday, March 9, 2015

Java non-blocking IO file server and client

Have always felt that the server creating one thread for each incoming request is a bit messy. Knowing that Java non-blocking IO is a cure for this, could not resist the temptation in trying it out.

So here I have implemented a file server and the corresponding file client using Java non-blocking IO.

With non-blocking IO, the server can handle all client requests in a single thread, need less system resource, therefore is capable of handling more client requests compared to the blocking IO implementation, but not without any disadvantage. As all clients' data are handled in single thread, with a selector, extra complication in the implementation is the price to pay, compared to blocking IO implementation.

So far it supports the following features:
- List files on the server. when the path is given as an empty string array, the file list of the whole root data directory of the server is returned.
- Send file to the server with a path indicating the location where the file is to be stored.
- Get file from the server with a path relative to the root data directory.

The following is some implementation details:

On OS X and Linux, "/" is used as path separator, (e.g., /home/user/data/) while on Windows, it uses "\" instead, (e.g. C:\users\data). To overcome this issue, a path when sent between server and client, is broken into a series of strings, e.g. to retrieve a file "/mydata/file.txt" located in the server root data directory "/home/user/svrdata", the client will send the path as a string array {"mydata" "file.txt"} to the server without path separator, the server receives the string array and converts it into a proper path accordingly.

The file server only needs two parameters:
- port number: on which it listens for the incoming requests
- root data directory: where the data files from the clients will be stored

The file client connects to the server by its IP address and the port. The file client can be used in a sequential manner, i.e. all tasks are executed one after another in one single thread; or in a random manner by either employing a thread pool, or just creating new thread. Examples are given in the main() for each manner.

The project can be found on:

https://github.com/kevinwang1975/NIOFileServer

To get the source code:

git clone https://github.com/kevinwang1975/NIOFileServer

Saturday, February 28, 2015

Compare A* with Dijkstra algorithm

A* (A Star) algorithm, as I have heard, has been widely used in games for path search. As I am not really a game person, have not played that many games myself, so cannot really provide any reference here. And Dijkstra algorithm is also very well-known, the one example I know is Cisco route uses the algorithm for finding the shortest path between two networking nodes. There is tons of pieces of information (discussions/articles) that describes the details about these algorithms, but I am more a visual person, really need to see it with my own eyes. So I decided to implements the two algorithms myself, and visualize it to be able to measure the difference quantitatively. OK, here it's.

http://youtu.be/g024lzsknDo


The green cell is the departure, the red cell is the destination, while the path is in yellow. The A* algorithm uses heuristics, so is almost always faster than Dijkstra algorithm, however, the path it finds may not be the shortest/most-optimal one, which is a trade for the speed. Even though Dijkstra algorithm came earlier than A*, A* can be seen as a more general form of Dijkstra, a "Dijkstra with heuristics.

The project can be found on:

https://github.com/kevinwang1975/PathFinder

The project contains the Java implementation of the A* and Dijkstra path search algorithms, which can be used alone in any application. A GUI demo is provided for the visualization that animates the search progress, also shows the cost of the path and the number of nodes visited during the search, so the difference between the two algorithm could not be more clear.

To get the source code:

git clone https://github.com/kevinwang1975/PathFinder