Tuesday, April 08, 2014

Parameterized JUnit Tests by Example


public class ReverseString {

 public static void main(String[] args) {
  String str = "abracadabra0";
  System.out.println(reverseStr(str));
 }

 public static String reverseStr(String str) {
  StringBuilder sb = new StringBuilder();
  for (int i = str.length() - 1; i >= 0; i--) {
   sb.append(str.charAt(i));
  }
  return sb.toString();
 }

}
import static org.junit.Assert.assertEquals;

import java.util.Arrays;

import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameters;

@RunWith(Parameterized.class)
public class ReverseStringTest {
 String testStr = "";
 String expectedStr = "";
 

 @Rule
 public ExpectedException exception = ExpectedException.none();

 public ReverseStringTest(String ts, String es) {
  this.testStr = ts;
  this.expectedStr = es;
 }
 
 @Parameters
 public static Iterable data() {
  return Arrays
    .asList(new Object[][] { { "abracadabra0", "0arbadacarba" },
      { null, null }, { "", "" } });
 }


 @Test
 public void test() {
  if (testStr == null) {
   exception.expect(NullPointerException.class);
  }
  assertEquals(expectedStr, ReverseString.reverseStr(testStr));
 }

}

Java Annotations by Example


import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * Annotations are defined via the @interface annotation before the class name.
 * Via @Retention you define if the annotation should be retained at runtime or
 * not. The @Target annotation lets you define where this annotation can be
 * used, e.g. the class, fields, methods, etc.
 * 
 * @author Watsh
 * 
 */
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface CanRun {

}
public class AnnotatedMethodsClass {

    public void method1() {
        System.out.println("method1");
    }

    @CanRun
    public void method2() {
        System.out.println("method2");
    }

    @CanRun
    public void method3() {
        System.out.println("method3");
    }

    public void method4() {
        System.out.println("method4");
    }

    public void method5() {
        System.out.println("method5");
    }

} 
import java.lang.reflect.Method;

public class AnnotationAnalyzer {

 /**
  * The main method of this class analyzes the annotations and calls the
  * corresponding methods.
  * 
  * @param args
  */
 public static void main(String[] args) {
  AnnotatedMethodsClass clz = new AnnotatedMethodsClass();
  Method[] methods = clz.getClass().getMethods();

  for (Method m : methods) {
   CanRun annos = m.getAnnotation(CanRun.class);
   if (annos != null) {
    try {
     m.invoke(clz);
    } catch (Exception e) {
     e.printStackTrace();
    }
   }
  }
 }
}

Sunday, April 06, 2014

Map Reduce - Overview

MapReduce is a parallel and distributed solution approach developed by Google for processing large datasets. Described in this paper - http://research.google.com/archive/mapreduce.html
Map transforms a set of data into key value pairs and Reduce aggregates this data into a scalar. A reducer receives all the data for an individual "key" from all the mappers.
The approach assumes that there are no dependencies between the input data. This make it easy to parallelize the problem. The number of parallel reduce task is limited by the number of distinct "key" values which are emitted by the map function.
MapReduce incorporates usually also a framework which supports MapReduce operations. A master controls the whole MapReduce process. The MapReduce framework is responsible for load balancing, re-issuing task if a worker as failed or is to slow, etc. The master divides the input data into separate units, send individual chunks of data to the mapper machines and collects the information once a mapper is finished. If the mapper are finished then the reducer machines will be assigned work. All key/value pairs with the same key will be send to the same reducer.
The classical example for using MapReduce is logfile analysis.

Big logfiles are split and a mapper search for different webpages which are accessed. Every time a webpage is found in the log a key / value pair is emitted to the reducer where the key is the webpage and the value is "1". The reducers aggregate the number of for certain webpages. As a end result you have the total number of hits for each webpage.

REST: JAX-RS by Example

REST

Annotation
Description
@PATH(your_path)
Sets the path to base URL + /your_path. The base URL is based on your application name, the servlet and the URL pattern from the web.xmlconfiguration file.
@POST, @GET, @PUT, @DELETE
Indicates that the following method will answer to an HTTP POST/GET/PUT/DELETE request, respectively.
@Produces(MediaType.TEXT_PLAIN[, more-types])
@Produces defines which MIME type is delivered by a method annotated with @GET.
@Consumes(type[, more-types])
@Consumes defines which MIME type is consumed by this method.
@PathParam
Used to inject values from the URL into a method parameter. This way you inject, for example, the ID of a resource into the method to get the correct object.

import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;

//Plain old Java Object it does not extend as class or implements
//an interface

//The class registers its methods for the HTTP GET request using the @GET annotation.
//Using the @Produces annotation, it defines that it can deliver several MIME types,
//text, XML and HTML.

//The browser requests per default the HTML MIME type.

//Sets the path to base URL + /hello
@Path("/hello")
public class Hello {
// This method is called if TEXT_PLAIN is request
 @GET
 @Produces(MediaType.TEXT_PLAIN)
 public String sayPlainTextHello() {
   return "Hello Jersey";
 }

 // This method is called if XML is request
 @GET
 @Produces(MediaType.TEXT_XML)
 public String sayXMLHello() {
   return "<?xml version=\"1.0\"?>" + "<hello> Hello Jersey" + "</hello>";
 }

 // This method is called if HTML is request
 @GET
 @Produces(MediaType.TEXT_HTML)
 public String sayHtmlHello() {
   return "<html> " + "<title>" + "Hello Jersey" + "</title>"
       + "<body><h1>" + "Hello Jersey" + "</body></h1>" + "</html> ";
 }

}

import static org.junit.Assert.assertEquals;

import java.net.URI;

import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.UriBuilder;

import org.junit.BeforeClass;
import org.junit.Test;

import com.sun.jersey.api.client.Client;
import com.sun.jersey.api.client.ClientResponse;
import com.sun.jersey.api.client.WebResource;
import com.sun.jersey.api.client.config.ClientConfig;
import com.sun.jersey.api.client.config.DefaultClientConfig;

public class HelloTest {

          private static WebResource service;

          @BeforeClass
          public static void setUpBeforeClass() throws Exception {
                   ClientConfig config = new DefaultClientConfig();
                   Client client = Client.create(config);
                   service = client.resource(getBaseURI());
          }

          @Test
          public void testSayPlainTextHello() {
                   String msg = service.path("rest").path("hello")
                                      .accept(MediaType.TEXT_PLAIN).get(ClientResponse.class)
                                      .toString();
                   System.out.println(msg);
                   assertEquals(true, msg.contains("200"));
          }

          private static URI getBaseURI() {
                   return UriBuilder.fromUri("http://localhost:8080/rest").build();
          }

}

A more complete example will be a todo service:
package rest.todo;

import javax.xml.bind.annotation.XmlRootElement;

@XmlRootElement
// JAX-RS supports an automatic mapping from JAXB annotated class to XML and
// JSON
public class Todo {
private String id;
private String summary;
private String description;

public Todo() {

}

public Todo(String id, String summary) {
this.id = id;
this.summary = summary;
}

public String getSummary() {
return summary;
}

public void setSummary(String summary) {
this.summary = summary;
}

public String getDescription() {
return description;
}

public void setDescription(String description) {
this.description = description;
}

public String getId() {
return id;
}

public void setId(String id) {
this.id = id;
}

}

package rest.todo;

import java.util.HashMap;
import java.util.Map;

public enum TodoDao {
instance;

private Map contentProvider = new HashMap();

private TodoDao() {

Todo todo = new Todo("1", "Learn REST");
todo.setDescription("Read http://www.vogella.com/tutorials/REST/article.html");
contentProvider.put("1", todo);
todo = new Todo("2", "Do something");
todo.setDescription("Read complete http://www.vogella.com");
contentProvider.put("2", todo);

}

public Map getModel() {
return contentProvider;
}

}

package rest.todo;

import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
import javax.ws.rs.PUT;
import javax.ws.rs.Produces;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Request;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriInfo;
import javax.xml.bind.JAXBElement;

public class TodoResource {
@Context
UriInfo uriInfo;
@Context
Request request;
String id;

public TodoResource(UriInfo uriInfo, Request request, String id) {
this.uriInfo = uriInfo;
this.request = request;
this.id = id;
}

// Application integration
@GET
@Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
public Todo getTodo() {
Todo todo = TodoDao.instance.getModel().get(id);
if (todo == null)
throw new RuntimeException("Get: Todo with " + id + " not found");
return todo;
}

// for the browser
@GET
@Produces(MediaType.TEXT_XML)
public Todo getTodoHTML() {
Todo todo = TodoDao.instance.getModel().get(id);
if (todo == null)
throw new RuntimeException("Get: Todo with " + id + " not found");
return todo;
}

@PUT
@Consumes(MediaType.APPLICATION_XML)
public Response putTodo(JAXBElement todo) {
Todo c = todo.getValue();
return putAndGetResponse(c);
}

@DELETE
public void deleteTodo() {
Todo c = TodoDao.instance.getModel().remove(id);
if (c == null)
throw new RuntimeException("Delete: Todo with " + id + " not found");
}

private Response putAndGetResponse(Todo todo) {
Response res;
if (TodoDao.instance.getModel().containsKey(todo.getId())) {
res = Response.noContent().build();
} else {
res = Response.created(uriInfo.getAbsolutePath()).build();
}
TodoDao.instance.getModel().put(todo.getId(), todo);
return res;
}
}

package rest.todo;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import javax.servlet.http.HttpServletResponse;
import javax.ws.rs.Consumes;
import javax.ws.rs.FormParam;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Request;
import javax.ws.rs.core.UriInfo;

//Will map the resource to the URL todos
@Path("/todos")
public class TodosResource {
// Allows to insert contextual objects into the class,
// e.g. ServletContext, Request, Response, UriInfo
@Context
UriInfo uriInfo;
@Context
Request request;

// Return the list of todos to the user in the browser
@GET
@Produces(MediaType.TEXT_XML)
public List getTodosBrowser() {
List todos = new ArrayList();
todos.addAll(TodoDao.instance.getModel().values());
return todos;
}

// Return the list of todos for applications
@GET
@Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
public List getTodos() {
List todos = new ArrayList();
todos.addAll(TodoDao.instance.getModel().values());
return todos;
}

// to get the total number of records
@GET
@Path("count")
@Produces(MediaType.TEXT_PLAIN)
public String getCount() {
int count = TodoDao.instance.getModel().size();
return String.valueOf(count);
}

@POST
@Produces(MediaType.TEXT_HTML)
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
public void newTodo(@FormParam("id") String id,
@FormParam("summary") String summary,
@FormParam("description") String description,
@Context HttpServletResponse servletResponse) throws IOException {
Todo todo = new Todo(id, summary);
if (description != null) {
todo.setDescription(description);
}
TodoDao.instance.getModel().put(id, todo);

servletResponse.sendRedirect("../create_todo.html");
}

// Defines that the next path parameter after todos is
// treated as a parameter and passed to the TodoResources
// Allows to type http://localhost:8080/de.vogella.jersey.todo/rest/todos/1
// 1 will be treaded as parameter todo and passed to TodoResource
@Path("{todo}")
public TodoResource getTodo(@PathParam("todo") String id) {
return new TodoResource(uriInfo, request, id);
}
}

And finally a test client:

package rest.todo;

import java.net.URI;

import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.UriBuilder;

import org.junit.BeforeClass;
import org.junit.Test;

import com.sun.jersey.api.client.Client;
import com.sun.jersey.api.client.WebResource;
import com.sun.jersey.api.client.config.ClientConfig;
import com.sun.jersey.api.client.config.DefaultClientConfig;

public class TodoTest {

private static WebResource service;

@BeforeClass
public static void setUpBeforeClass() throws Exception {
ClientConfig config = new DefaultClientConfig();
Client client = Client.create(config);
service = client.resource(getBaseURI());
}

@Test
public void test() {
// Get XML
System.out.println(service.path("rest").path("todo")
.accept(MediaType.TEXT_XML).get(String.class));
// Get XML for application
System.out.println(service.path("rest").path("todo")
.accept(MediaType.APPLICATION_JSON).get(String.class));
// Get JSON for application
System.out.println(service.path("rest").path("todo")
.accept(MediaType.APPLICATION_XML).get(String.class));
}

private static URI getBaseURI() {
return UriBuilder.fromUri(
"http://localhost:8080/rest").build();
}

}


Java Messaging Service 1.1 - Overview

JMS 

Administrative tools allow you to bind destinations and connection factories into a JNDI namespace. A JMS client can then use resource injection to access the administered objects in the namespace and then establish a logical connection to the same objects through the JMS provider.

Point to point messaging

·         Each message has only one consumer.
·         A sender and a receiver of a message have no timing dependencies. The receiver can fetch the message whether or not it was running when the client sent the message.
·         The receiver acknowledges the successful processing of a message.
Use PTP messaging when every message you send must be processed successfully by one consumer.


Publish/subscribe messaging


·         Each message can have multiple consumers.
·         Publishers and subscribers have a timing dependency. A client that subscribes to a topic can consume only messages published after the client has created a subscription, and the subscriber must continue to be active in order for it to consume messages.

The JMS API relaxes this timing dependency to some extent by allowing subscribers to create durable subscriptions, which receive messages sent while the subscribers are not active.
Use pub/sub messaging when each message can be processed by any number of consumers (or none).
Messages could be consumed – synchronously (blocking w/ timeout) or asynchronously (provider calls onMessage() of listener).
The basic building blocks of a JMS application are:
·         Administered objects: connection factories and destinations
·         Connections
·         Sessions
·         Message producers
·         Message consumers
·         Messages
An EJB Client – message producer.
import helloworld.beans.SingletonHelloWorldBeanRemote;
import helloworld.vo.GreetingRequest;
import javax.jms.Connection;
import javax.jms.ConnectionFactory;
import javax.jms.Destination;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.MessageProducer;
import javax.jms.Session;
import javax.jms.TextMessage;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;

/**
 * The message producer.
 * @author rwatsh
 */
public class MessageProducerApp {

    private static Message createJMSMessageForjmsHelloWorldQueue(Session session, Object messageData) throws JMSException {
        // TODO create and populate message to send
        TextMessage tm = session.createTextMessage();
        tm.setText(messageData.toString());
        return tm;
    }

    private static void sendJMSMessageToHelloWorldQueue(Object messageData) throws NamingException, JMSException {
        Context c = new InitialContext();
        ConnectionFactory cf = (ConnectionFactory) c.lookup("jms/HelloWorldQueueFactory");
        Connection conn = null;
        Session s = null;
        try {
            conn = cf.createConnection();
            s = conn.createSession(false, s.AUTO_ACKNOWLEDGE);
            Destination destination = (Destination) c.lookup("jms/HelloWorldQueue");
            MessageProducer mp = s.createProducer(destination);
            mp.send(createJMSMessageForjmsHelloWorldQueue(s, messageData));
        } finally {
            if (s != null) {
                try {
                    s.close();
                } catch (JMSException e) {
                    System.err.println("Cannot close session - " + e);
                }
            }
            if (conn != null) {
                conn.close();
            }
        }
    }


    private static SingletonHelloWorldBeanRemote lookupSingletonHelloWorldBeanRemote() {
        try {
            Context c = new InitialContext();
            return (SingletonHelloWorldBeanRemote) c.lookup("java:global/EJB31/EJB31-ejb/SingletonHelloWorldBean");
        } catch (NamingException ne) {
            ne.printStackTrace();
            throw new RuntimeException(ne);
        }
    }

    public static void main(String[] args) {
        SingletonHelloWorldBeanRemote hwr = lookupSingletonHelloWorldBeanRemote();
        GreetingRequest result = hwr.sayHello();
        String resultStr = result.toString();
        try {
            sendJMSMessageToHelloWorldQueue(resultStr);
            System.out.println("MessageProducerApp.main: sent message - " + resultStr);
        } catch (Exception ex) {
            System.err.println("MessageProducerApp.main: failed to send message - " + ex);
        }

    }
}
MDB message receiver:

import helloworld.vo.GreetingRequest;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import javax.ejb.ActivationConfigProperty;
import javax.ejb.MessageDriven;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.MessageListener;
import javax.jms.ObjectMessage;
import javax.jms.TextMessage;

/**
 * MDB that consumes the message.
 * @author rwatsh
 */
@MessageDriven(mappedName = "jms/HelloWorldQueue", activationConfig = {
    @ActivationConfigProperty(propertyName = "acknowledgeMode", propertyValue = "Auto-acknowledge"),
    @ActivationConfigProperty(propertyName = "destinationType", propertyValue = "javax.jms.Queue")
})
public class HelloWorldMDB implements MessageListener {

    public HelloWorldMDB() {
    }

    @PostConstruct
    private void postConstruct() {
        System.out.println("HelloWorldMDB: @PostConstruct");
    }

    @Override
    public void onMessage(Message message) {
        if (message instanceof TextMessage) {
            try {
                TextMessage textMessage = (TextMessage) message;
                String messageValue = textMessage.getText();
                System.out.println("HelloWorldMDB.onMessage: received text message - " + messageValue);
            } catch (JMSException ex) {
                Logger.getLogger(HelloWorldMDB.class.getName()).log(Level.SEVERE, null, ex);
            }

        } else if (message instanceof ObjectMessage) {
            try {
                ObjectMessage objMessage = (ObjectMessage) message;
                Object contents = objMessage.getObject();
                if (contents instanceof GreetingRequest) {
                    String messageValue = contents.toString();
                    System.out.println("HelloWorldMDB.onMessage: received object message - " + messageValue);
                }
            } catch (JMSException ex) {
            }

        } else {
//do nothing
        }
    }

    @PreDestroy
    private void destroy() {
        System.out.println("HelloWorldMDB: @PreDestroy");
    }
}

CAP Theorem

Proposed by Eric Brewer. States that it is impossible for a distributed computer system to simultaneously provide all three of the following guarantees:

Consistency – all nodes see the same data at the same time
Availability – a guarantee that every request receives a response about whether it was successful or failed
Partition tolerance – the system continues to operate despite arbitrary message loss when network is partitioned.

CA = If network is partitioned, the nodes continue to be available by themselves and data continues to be consistent on the same node even when there is no partition tolerance.
AP = Nodes may still be available even when we ensure partition tolerance by disallowing further writes but data will not remain consistent between the nodes anymore as nodes cannot exchange message due to network partitioning.
PC = Nodes may be consistent but in order to ensure partition tolerance they may not be available to write.


Object Oriented Programming Principles - SOLID

SOLID

1. Single Responsibility Principlethere should not be more than one reason for a class to change, or a class should always handle single functionality. If you put more than one functionality in one Class in Java  it introduce coupling between two functionality and even if you change one functionality there is chance you broke coupled functionality,  which require another round of testing to avoid any surprise on production environment.

2. Open/Closed principle Classes, methods or functions should be Open for extension (new functionality) and Closed for modification.  The idea was that once completed, the implementation of a class could only be modified to correct errors; new or changed features would require that a different class be created. That class could reuse coding from the original class through inheritance. The derived subclass might or might not have the same interface as the original class.
Meyer's definition advocates implementation inheritance. Implementation can be reused through inheritance but interface specifications need not be. The existing implementation is closed to modifications, and new implementations need not implement the existing interface.

3. Liskov substitution principle - “objects in a program should be replaceable with instances of their subtypes without altering the correctness of that program.” 

4. Interface segregation principle - “many client-specific interfaces are better than one general-purpose interface.

5. Dependency inversion principle - one should “Depend upon Abstractions. Do not depend upon concretions.

The principle states:
A. High-level modules should not depend on low-level modules. Both should depend on abstractions.
B. Abstractions should not depend on details. Details should depend on abstractions.

This is facilitated by the separation of high-level components and low-level components into separate packages/libraries, where interfaces defining the behavior/services required by the high-level component are owned by, and exist within the high-level component's package. The implementation of the high-level component's interface by the low level component requires that the low-level component package depend upon the high-level component for compilation, thus inverting the conventional dependency relationship. 
Another way to think of it is,
Low level components = server side
High level components = client side

Both server and client sides depend on the same interface (contract). The server side needs to implement the interface required by client side. The interface source files are required for server side compilation as well. This brings in the dependency of server side on client side (which is inverse of the dependency of client on server).

 Various patterns such as Plugin, Service Locator, or Dependency Injection are then employed to facilitate the run-time provisioning of the chosen low-level component implementation to the high-level component.

Tuesday, April 01, 2014

Design Patterns - Behavioral

Behavioral

1.       Chain of Responsibility - delegates commands to a chain of processing objects.
interface Chain {

       public abstract void setNext(Chain nextInChain);

       public abstract void process(Number request);
}

class Number {
       private int number;

       public Number(int number) {
              this.number = number;
       }

       public int getNumber() {
              return number;
       }

}

class NegativeProcessor implements Chain {

       private Chain nextInChain;

       public void setNext(Chain c) {
              nextInChain = c;
       }

       public void process(Number request) {
              if (request.getNumber() < 0) {
                     System.out.println("NegativeProcessor : " + request.getNumber());
              } else {
                     nextInChain.process(request);
              }
       }
}

class ZeroProcessor implements Chain {

       private Chain nextInChain;

       public void setNext(Chain c) {
              nextInChain = c;
       }

       public void process(Number request) {
              if (request.getNumber() == 0) {
                     System.out.println("ZeroProcessor : " + request.getNumber());
              } else {
                     nextInChain.process(request);
              }
       }
}

class PositiveProcessor implements Chain {

       private Chain nextInChain;

       public void setNext(Chain c) {
              nextInChain = c;
       }

       public void process(Number request) {
              if (request.getNumber() > 0) {
                     System.out.println("PositiveProcessor : " + request.getNumber());
              } else {
                     nextInChain.process(request);
              }
       }
}

public class ChainOfResponsibilityExample {
       public static void main(String[] args) {
              // configure Chain of Responsibility
              Chain c1 = new NegativeProcessor();
              Chain c2 = new ZeroProcessor();
              Chain c3 = new PositiveProcessor();
              c1.setNext(c2);
              c2.setNext(c3);

              // calling chain of responsibility
              c1.process(new Number(99));
              c1.process(new Number(-30));
              c1.process(new Number(0));
              c1.process(new Number(100));
       }
}

Chain of responsibility (recognizeable by behavioral methods which (indirectly) invokes the same method in another implementation of same abstract/interface type in a queue)

2.       Command - creates objects which encapsulate actions and parameters.
import java.util.ArrayList;
import java.util.List;

interface ConsumerElectronics {
          public abstract void on();

          public abstract void mute();
}

class Television implements ConsumerElectronics {

          public void on() {
                   System.out.println("Television is on!");
          }

          @Override
          public void mute() {
                   System.out.println("Television is muted!");

          }
}

class SoundSystem implements ConsumerElectronics {

          public void on() {
                   System.out.println("Sound system is on!");
          }

          @Override
          public void mute() {
                   System.out.println("Sound system is muted!");

          }
}

interface Command {

          public abstract void execute();

}

class OnCommand implements Command {

          private ConsumerElectronics ce;

          public OnCommand(ConsumerElectronics ce) {
                   this.ce = ce;
          }

          public void execute() {
                   ce.on();
          }
}

class MuteAllCommand implements Command {
          List ceList;

          public MuteAllCommand(List ceList) {
                   this.ceList = ceList;
          }

          @Override
          public void execute() {

                   for (ConsumerElectronics ce : ceList) {
                             ce.mute();
                   }

          }
}

class Button {
          Command c;

          public Button(Command c) {
                   this.c = c;
          }

          public void click() {
                   c.execute();
          }
}

class UniversalRemote {

          public static ConsumerElectronics getActiveDevice() {
                   // here we will have a complex electronic circuit :-)
                   // that will maintain current device
                   Television tv = new Television();
                   return tv;
          }
}

Command (recognizeable by behavioral methods in an abstract/interface type which invokes a method in an implementation of adifferent abstract/interface type which has been encapsulated by the command implementation during its creation)

·      All implementations of java.lang.Runnable
·      All implementations of javax.swing.Action
3.       Interpreter - implements a specialized language.

import java.util.Stack;

interface IExpression {
          public int interpret();
}
/** Terminal Expression */
class NumberExpression implements IExpression {
          int number;

          public NumberExpression(int i) {
                   number = i;
          }

          public NumberExpression(String s) {
                   number = Integer.parseInt(s);
          }

          @Override
          public int interpret() {
                   return number;
          }

}
/** Non-terminal expression */
class MultiplyExpression implements IExpression {

          IExpression leftExpression;
          IExpression rightExpresion;

          public MultiplyExpression(IExpression leftExpression,
                             IExpression rightExpresion) {
                   this.leftExpression = leftExpression;
                   this.rightExpresion = rightExpresion;
          }

          @Override
          public int interpret() {

                   return leftExpression.interpret() * rightExpresion.interpret();
          }

}

class PlusExpression implements IExpression {
          IExpression leftExpression;
          IExpression rightExpresion;

          public PlusExpression(IExpression leftExpression, IExpression rightExpresion) {
                   this.leftExpression = leftExpression;
                   this.rightExpresion = rightExpresion;
          }

          @Override
          public int interpret() {
                   return leftExpression.interpret() + rightExpresion.interpret();
          }

}

class MinusExpression implements IExpression {

          IExpression leftExpression;
          IExpression rightExpresion;

          public MinusExpression(IExpression leftExpression,
                             IExpression rightExpresion) {
                   this.leftExpression = leftExpression;
                   this.rightExpresion = rightExpresion;
          }

          @Override
          public int interpret() {

                   return leftExpression.interpret() - rightExpresion.interpret();
          }

}

/*-
 * Postfix calculator.
 *
 * Algorithm for postfix expression parser implementation is simpler than for
 * infix.
 *
 * Read token one by one and loop till end of expression
 * Is read element a number
 * 1. true then, push it to a stack
 * 2. false then,
 *    1. pop two elements from stack
 *    2. apply the operator
 *    3. push the result to stack
 *
 */
public class InterpreterExample {
          public static void main(String args[]) {
                   String tokenString = "4 3 2 - 1 + *";
                   Stack stack = new Stack();

                   String[] tokenList = tokenString.split(" ");
                   for (String s : tokenList) {
                             if (isOperator(s)) {
                                      IExpression rightExpression = stack.pop();
                                      IExpression leftExpression = stack.pop();
                                      IExpression operator = getOperatorInstance(s, leftExpression,
                                                          rightExpression);
                                      int result = operator.interpret();
                                      stack.push(new NumberExpression(result));
                             } else {
                                      IExpression i = new NumberExpression(s);
                                      stack.push(i);
                             }
                   }
                   System.out.println("Result: " + stack.pop().interpret());
          }

          public static boolean isOperator(String s) {
                   if (s.equals("+") || s.equals("-") || s.equals("*"))
                             return true;
                   else
                             return false;
          }

          public static IExpression getOperatorInstance(String s, IExpression left,
                             IExpression right) {
                   switch (s) {
                   case "+":
                             return new PlusExpression(left, right);
                   case "-":
                             return new MinusExpression(left, right);
                   case "*":
                             return new MultiplyExpression(left, right);
                   }
                   return null;
          }
}

Interpreter (recognizeable by behavioral methods returning a structurally different instance/type of the given instance/type; note that parsing/formatting is not part of the pattern, determining the pattern and how to apply it is)

·      java.util.Pattern
·      java.text.Normalizer
·      All subclasses of java.text.Format
·      All subclasses of javax.el.ELResolver

4.       Iterator - accesses the elements of an object sequentially without exposing its underlying representation.
import java.util.ArrayList;
import java.util.List;

class Animal {
          private String animalName;
          private String animalType;

          public Animal(String animalName, String animalType) {
                   this.animalName = animalName;
                   this.animalType = animalType;
          }

          public String getAnimalName() {
                   return animalName;
          }

          public void setAnimalName(String animalName) {
                   this.animalName = animalName;
          }

          public String getAnimalType() {
                   return animalType;
          }

          public void setAnimalType(String animalType) {
                   this.animalType = animalType;
          }
}

interface Iterator {
          public Animal nextAnimal();

          public boolean isLastAnimal();

          public Animal currentAnimal();
}

class WildIterator implements Iterator {

          public List animalList;
          private int position;

          public WildIterator(List animalList) {
                   this.animalList = animalList;
          }

          @Override
          public Animal nextAnimal() {
                   Animal animal = null;
                   for (; position < animalList.size(); position++) {
                             if ("Wild".equals((animalList.get(position)).getAnimalType())) {
                                      animal = animalList.get(position);
                                      position++;
                                      break;
                             }
                   }
                   return animal;
          }

          @Override
          public boolean isLastAnimal() {
                   for (int i = position; i < animalList.size(); i++) {
                             if ("Wild".equals((animalList.get(i)).getAnimalType())) {
                                      return false;
                             }
                   }
                   return true;
          }

          @Override
          public Animal currentAnimal() {
                   if (position < animalList.size()) {
                             return animalList.get(position);
                   }
                   return null;
          }

}

class DomesticIterator implements Iterator {

          List animalList;
          private int position;

          public DomesticIterator(List animalList) {
                   this.animalList = animalList;
          }

          @Override
          public Animal nextAnimal() {
                   Animal animal = null;
                   for (; position < animalList.size(); position++) {
                             if ("Domestic".equals((animalList.get(position)).getAnimalType())) {
                                      animal = animalList.get(position);
                                      position++;
                                      break;
                             }
                   }
                   return animal;
          }

          @Override
          public boolean isLastAnimal() {
                   for (int i = position; i < animalList.size(); i++) {
                             if ("Domestic".equals((animalList.get(i)).getAnimalType())) {
                                      return false;
                             }
                   }
                   return true;
          }

          @Override
          public Animal currentAnimal() {
                   if (position < animalList.size()) {
                             return animalList.get(position);
                   }
                   return null;
          }

}

interface IZoo {

          public List getAnimals();

          public void addAnimal(Animal animal);

          public void removeAnimal(Animal animal);

          public Iterator createIterator(String iteratorType);
}

class ZooImpl implements IZoo {

          List animalList;

          public ZooImpl() {
                   animalList = new ArrayList();
          }

          @Override
          public List getAnimals() {

                   return animalList;
          }

          @Override
          public void addAnimal(Animal animal) {
                   animalList.add(animal);

          }

          @Override
          public void removeAnimal(Animal animal) {
                   animalList.remove(animal);

          }

          @Override
          public Iterator createIterator(String iteratorType) {
                   if ("Wild".equals(iteratorType)) {
                             return new WildIterator(animalList);
                   } else {
                             return new DomesticIterator(animalList);
                   }
          }
}

public class IteratorExample {
          public static void main(String args[]) {
                   ZooImpl zoo = new ZooImpl();
                   zoo.addAnimal(new Animal("Tiger", "Wild"));
                   zoo.addAnimal(new Animal("Lion", "Wild"));
                   zoo.addAnimal(new Animal("Tom Cat", "Domestic"));
                   zoo.addAnimal(new Animal("Raging Bull", "Wild"));
                   zoo.addAnimal(new Animal("Scooby Doo", "Domestic"));

                   Iterator wildIterator = zoo.createIterator("Wild");
                   while (!wildIterator.isLastAnimal()) {
                             System.out.println("Wild Animal: "
                                                + wildIterator.nextAnimal().getAnimalName());
                   }

                   Iterator domesticIterator = zoo.createIterator("Domestic");
                   while (!domesticIterator.isLastAnimal()) {
                             System.out.println("Domestic Animal: "
                                                + domesticIterator.nextAnimal().getAnimalName());
                   }
          }
}

Iterator (recognizeable by behavioral methods sequentially returning instances of a different type from a queue)

·      All implementations of java.util.Iterator (thus among others also java.util.Scanner!).
·      All implementations of java.util.Enumeration

As of Java 5, objects implementing the Iterable interface, which returns an Iterator from its only method, can be traversed using theenhanced for loop syntax.[2] The Collection interface from the Java collections framework extends Iterable.
5.       Mediator - allows loose coupling between classes by being the only class that has detailed knowledge of their methods.
interface IATCMediator {

          public void registerRunway(Runway runway);

          public void registerFlight(Flight flight);

          public boolean isLandingOk();

          public void setLandingStatus(boolean status);
}

interface ICommand {
          void land();
}

class Flight implements ICommand {
          private IATCMediator atcMediator;

          public Flight(IATCMediator atcMediator) {
                   this.atcMediator = atcMediator;
          }

          public void land() {
                   if (atcMediator.isLandingOk()) {
                             System.out.println("Landing done....");
                             atcMediator.setLandingStatus(true);
                   } else
                             System.out.println("Will wait to land....");
          }

          public void getReady() {
                   System.out.println("Getting ready...");
          }

}

class Runway implements ICommand {
          private IATCMediator atcMediator;

          public Runway(IATCMediator atcMediator) {
                   this.atcMediator = atcMediator;
                   atcMediator.setLandingStatus(true);
          }

          @Override
          public void land() {
                   System.out.println("Landing permission granted...");
                   atcMediator.setLandingStatus(true);
          }

}

class ATCMediator implements IATCMediator {
          private Flight flight;
          private Runway runway;
          public boolean land;

          public void registerRunway(Runway runway) {
                   this.runway = runway;
          }

          public void registerFlight(Flight flight) {
                   this.flight = flight;
          }

          public boolean isLandingOk() {
                   return land;
          }

          @Override
          public void setLandingStatus(boolean status) {
                   land = status;

          }
}

public class MediatorExample {
          public static void main(String args[]) {

                   IATCMediator atcMediator = new ATCMediator();
                   Flight sparrow101 = new Flight(atcMediator);
                   Runway mainRunway = new Runway(atcMediator);
                   atcMediator.registerFlight(sparrow101);
                   atcMediator.registerRunway(mainRunway);
                   sparrow101.getReady();
                   mainRunway.land();
                   sparrow101.land();
          }
}

Mediator (recognizeable by behavioral methods taking an instance of different abstract/interface type (usually using the command pattern) which delegates/uses the given instance)

·      java.util.Timer (all scheduleXXX() methods)
·      java.util.concurrent.ExecutorService (the invokeXXX() and submit() methods)
·      java.util.concurrent.ScheduledExecutorService (all scheduleXXX() methods)
6.       Memento - provides the ability to restore an object to its previous state (undo).
import java.util.ArrayList;
import java.util.List;

class Memento {
          private String state;

          public Memento(String state) {
                   this.state = state;
          }

          public String getState() {
                   return state;
          }
}

class Originator {

          // this String is just for example
          // in real world application this
          // will be a java class - the object
          // for which the state to be stored
          private String state;

          public void setState(String state) {
                   this.state = state;
          }

          public String getState() {
                   return state;
          }

          public Memento createMemento() {
                   return new Memento(state);
          }

          public void setMemento(Memento memento) {
                   state = memento.getState();
          }
}

class Caretaker {
          private List statesList = new ArrayList();

          public void addMemento(Memento m) {
                   statesList.add(m);
          }

          public Memento getMemento(int index) {
                    return statesList.get(index);
          }
}

public class MementoExample {
          public static void main(String[] args) {
                   Originator originator = new Originator();
                   originator.setState("Lion");
                   Memento memento = originator.createMemento();
                   Caretaker caretaker = new Caretaker();
                   caretaker.addMemento(memento);

                   originator.setState("Tiger");
                   originator.setState("Horse");
                   memento = originator.createMemento();
                   caretaker.addMemento(memento);
                   originator.setState("Elephant");
                   System.out
                                      .println("Originator Current State: " + originator.getState());
                   System.out.println("Originator restoring to previous state...");
                   memento = caretaker.getMemento(1);
                   originator.setMemento(memento);
                   System.out
                                      .println("Originator Current State: " + originator.getState());
                   System.out.println("Again restoring to previous state...");
                   memento = caretaker.getMemento(0);
                   originator.setMemento(memento);
                   System.out
                                      .println("Originator Current State: " + originator.getState());
          }
}
7.       Observer - is a publish/subscribe pattern which allows a number of observer objects to see an event.

import java.util.ArrayList;
import java.util.List;

/*
 * Same as Observable.
 */
interface Subject {

          public void registerObserver(Observer observer);

          public void notifyObserver();

          public void unRegisterObserver(Observer observer);

          public Object getUpdate();

}

class Blog implements Subject {

          List observersList;
          private boolean stateChange;

          public Blog() {
                   this.observersList = new ArrayList();
                    stateChange = false;
          }

          public void registerObserver(Observer observer) {
                   observersList.add(observer);
          }

          public void unRegisterObserver(Observer observer) {
                   observersList.remove(observer);
          }

          public void notifyObserver() {

                   if (stateChange) {
                             for (Observer observer : observersList) {
                                      observer.update();
                             }
                   }
          }

          public Object getUpdate() {
                   Object changedState = null;
                   // should have logic to send the
                   // state change to querying observer
                   if (stateChange) {
                             changedState = "Observer Design Pattern";
                   }
                   return changedState;
          }

          public void postNewArticle() {
                   stateChange = true;
                   notifyObserver();
          }

}

interface Observer {

          public void update();

          public void setSubject(Subject subject);
}

class User implements Observer {

          private String article;
          private Subject blog;

          public void setSubject(Subject blog) {
                   this.blog = blog;
                   article = "No New Article!";
          }

          @Override
          public void update() {
                   System.out.println("State change reported by Subject.");
                   article = (String) blog.getUpdate();
          }

          public String getArticle() {
                   return article;
          }
}

public class ObserverExample {
          public static void main(String args[]) {
                   Blog blog = new Blog();
                   User user1 = new User();
                   User user2 = new User();
                   blog.registerObserver(user1);
                   blog.registerObserver(user2);
                   user1.setSubject(blog);
                   user2.setSubject(blog);

                   System.out.println(user1.getArticle());
                   blog.postNewArticle();
                   System.out.println(user1.getArticle());
          }
}

Observer (or Publish/Subscribe) (recognizeable by behavioral methods which invokes a method on an instance of anotherabstract/interface type, depending on own state)

·      java.util.Observer/java.util.Observable (rarely used in real world though)
·      All implementations of java.util.EventListener (practically all over Swing thus)

8.       State - allows an object to alter its behavior when it’s internal state changes.

/**
 * State interface.
 */
interface MobileAlertState {
          public void alert(AlertStateContext ctx);
}

class Vibration implements MobileAlertState {

          @Override
          public void alert(AlertStateContext ctx) {
                   System.out.println("vibration...");
          }
}

class Silent implements MobileAlertState {

          @Override
          public void alert(AlertStateContext ctx) {
                   System.out.println("silent...");
          }

}

/**
 * This class maintains the current state and is the core of the state design
 * pattern. A client should access / run the whole setup through this class.
 */
class AlertStateContext {
          private MobileAlertState currentState;

          public AlertStateContext() {
                   currentState = new Vibration();
          }

          public void setState(MobileAlertState state) {
                   currentState = state;
          }

          public void alert() {
                   currentState.alert(this);
          }
}

public class StateExample {
          public static void main(String[] args) {
                   AlertStateContext stateContext = new AlertStateContext();
                   stateContext.alert();
                   stateContext.alert();
                   stateContext.setState(new Silent());
                   stateContext.alert();
                   stateContext.alert();
                   stateContext.alert();
          }
}

State (recognizeable by behavioral methods which changes its behaviour depending on the instance's state which can be controlled externally)

·      javax.faces.lifecycle.LifeCycle#execute() (controlled by FacesServlet, the behaviour is dependent on current phase (state) of JSF lifecycle)

9.       Strategy - allows one of a family of algorithms to be selected on-the-fly at runtime.

/**
 * The classes that implement a concrete strategy should implement this. The
 * Context class uses this to call the concrete strategy.
 */
interface Strategy {
          int execute(int a, int b);
};

/** Implements the algorithm using the strategy interface */
class Add implements Strategy {
          public int execute(int a, int b) {
                   System.out.println("Called Add's execute()");
                   return a + b; // Do an addition with a and b
          }
};

class Subtract implements Strategy {
          public int execute(int a, int b) {
                   System.out.println("Called Subtract's execute()");
                   return a - b; // Do a subtraction with a and b
          }
};

class Multiply implements Strategy {
          public int execute(int a, int b) {
                   System.out.println("Called Multiply's execute()");
                   return a * b; // Do a multiplication with a and b
          }
};

// Configured with a ConcreteStrategy object and maintains
// a reference to a Strategy object
class Context {
          private Strategy strategy;

          public Context(Strategy strategy) {
                   this.strategy = strategy;
          }

          public int executeStrategy(int a, int b) {
                   return this.strategy.execute(a, b);
          }
};

/** Tests the pattern */
class StrategyExample {
          public static void main(String[] args) {
                   Context context;
                   // Three contexts following different strategies
                   context = new Context(new Add());
                   int resultA = context.executeStrategy(3, 4);

                   context = new Context(new Subtract());
                   int resultB = context.executeStrategy(3, 4);

                   context = new Context(new Multiply());
                   int resultC = context.executeStrategy(3, 4);

                   System.out.println("Result A : " + resultA);
                   System.out.println("Result B : " + resultB);
                   System.out.println("Result C : " + resultC);
          }
}

Strategy and open/closed principle[edit]


According to the strategy pattern, the behaviors of a class should not be inherited. Instead they should be encapsulated using interfaces. As an example, consider a car class. Two possible functionalities for car are brake and accelerate.
Since accelerate and brake behaviors change frequently between models, a common approach is to implement these behaviors in subclasses. This approach has significant drawbacks: accelerate and brake behaviors must be declared in each new Car model. The work of managing these behaviors increases greatly as the number of models increases, and requires code to be duplicated across models. Additionally, it is not easy to determine the exact nature of the behavior for each model without investigating the code in each.
The strategy pattern uses aggregation instead of inheritance. In the strategy pattern, behaviors are defined as separate interfaces and specific classes that implement these interfaces. Specific classes encapsulate these interfaces. This allows better decoupling between the behavior and the class that uses the behavior. The behavior can be changed without breaking the classes that use it, and the classes can switch between behaviors by changing the specific implementation used without requiring any significant code changes. Behaviors can also be changed at run-time as well as at design-time. For instance, a car object’s brake behavior can be changed from BrakeWithABS() to Brake() by changing the brakeBehavior member to:
brakeBehavior = new Brake();
This gives greater flexibility in design and is in harmony with the Open/closed principle (OCP) that states that classes should be open for extension but closed for modification.

Strategy (recognizeable by behavioral methods in an abstract/interface type which invokes a method in an implementation of adifferent abstract/interface type which has been passed-in as method argument into the strategy implementation)

·      java.util.Comparator#compare(), executed by among others Collections#sort().
·      javax.servlet.http.HttpServlet, the service() and all doXXX() methods takeHttpServletRequest and HttpServletResponse and the implementor has to process them (and not to get hold of them as instance variables!).

10.   Template Method - defines the skeleton of an algorithm as an abstract class, allowing its subclasses to provide concrete behavior.
The template method is used in frameworks, where each implements the invariant parts of a domain's architecture, leaving "placeholders" for customisation options. This is an example for inversion of control, also called the Hollywood principle. Reasons to use the template method are to:[4]
·         Let subclasses implement (through method overriding) behavior that can vary.
·         Avoid duplication in the code: the general workflow structure is implemented once in the abstract class's algorithm, and necessary variations are implemented in each of the subclasses.
·         Control at what point(s) subclassing is allowed. As opposed to a simple polymorphic override, where the base method would be entirely rewritten allowing radical change to the workflow, only the specific details of the workflow are allowed to change.
The control structure (inversion of control) that is the result of the application of a template pattern is often referred to as the Hollywood Principle: "Don't call us, we'll call you." Using this principle, the template method in a parent class controls the overall process by calling subclass methods as required.

import java.util.Random;

/**
 * An abstract class that is common to several games in which players play
 * against the others, but only one is playing at a given time.
 */

abstract class Game {

          protected int playersCount;

          abstract void initializeGame();

          abstract void makePlay(int player);

          abstract boolean endOfGame();

          abstract void printWinner();

          /* A template method : */
          public final void playOneGame(int playersCount) {
                   this.playersCount = playersCount;
                   initializeGame();
                   int j = 0;
                   while (!endOfGame()) {
                             makePlay(j);
                             j = (j + 1) % playersCount;
                   }
                   printWinner();
          }
}

// Now we can extend this class in order
// to implement actual games:

class Monopoly extends Game {
          private int currentPlayer;

          /* Implementation of necessary concrete methods */
          void initializeGame() {
                   // Initialize players
                   // Initialize money
          }

          void makePlay(int player) {
                   // Process one turn of player
                   System.out.println("Playing player: " + player);
                   this.currentPlayer = player;
          }

          boolean endOfGame() {
                   // Return true if game is over
                   // according to Monopoly rules
                   Random rand = new Random();
                   return rand.nextInt(100) < 5 ? true : false;
          }

          void printWinner() {
                   // Display who won
                   System.out.println("Winner of Monopoly game is player: "
                                      + currentPlayer);
          }
          /* Specific declarations for the Monopoly game. */

          // ...
}

class Chess extends Game {
          private int currentPlayer;

          /* Implementation of necessary concrete methods */
          void initializeGame() {
                   // Initialize players
                   // Put the pieces on the board
          }

          void makePlay(int player) {
                   // Process a turn for the player
                   System.out.println("Playing player: " + player);
                   this.currentPlayer = player;
          }

          boolean endOfGame() {
                   // Return true if in Checkmate or
                   // Stalemate has been reached
                   Random rand = new Random();
                   return rand.nextInt(100) < 10 ? true : false;
          }

          void printWinner() {
                   System.out.println("Winner of Chess game is player: " + currentPlayer);
          }
          /* Specific declarations for the chess game. */

          // ...
}

public class TemplateMethodExample {
          public static void main(String[] args) {
                   Game g1 = new Chess();
                   g1.playOneGame(2);
                  
                   Monopoly m1 = new Monopoly();
                   m1.playOneGame(4);
          }
}

Template method (recognizeable by behavioral methods which already have a "default" behaviour definied by an abstract type)

·      All non-abstract methods of java.io.InputStreamjava.io.OutputStreamjava.io.Readerand java.io.Writer.
·      All non-abstract methods of java.util.AbstractListjava.util.AbstractSet andjava.util.AbstractMap.
·      javax.servlet.http.HttpServlet, all the doXXX() methods by default sends a HTTP 405 "Method Not Allowed" error to the response. You're free to implement none or any of them.

11.   Visitor - separates an algorithm from an object structure by moving the hierarchy of methods into one object.

In the example below, every car element has to do perform same algorithm (print and do, but in their own way) so we can take out the algorithms into their own classes and invoke them when the corresponding visit method is called. In future more algorithms may be added to all car elements as a new class extending CarElementVisitor.

interface ICarElementVisitor {
          void visit(Wheel wheel);

          void visit(Engine engine);

          void visit(Body body);

          void visit(Car car);
}

interface ICarElement {
          void accept(ICarElementVisitor visitor); // CarElements have to provide
                                                                                                                   // accept().
}

class Wheel implements ICarElement {
          private String name;

          public Wheel(String name) {
                   this.name = name;
          }

          public String getName() {
                   return this.name;
          }

          public void accept(ICarElementVisitor visitor) {
                   /*
                    * accept(ICarElementVisitor) in Wheel implements
                    * accept(ICarElementVisitor) in ICarElement, so the call to accept is
                    * bound at run time. This can be considered the first dispatch.
                    * However, the decision to call visit(Wheel) (as opposed to
                    * visit(Engine) etc.) can be made during compile time since 'this' is
                    * known at compile time to be a Wheel. Moreover, each implementation of
                    * ICarElementVisitor implements the visit(Wheel), which is another
                    * decision that is made at run time. This can be considered the second
                    * dispatch.
                    */
                   visitor.visit(this);
          }
}

class Engine implements ICarElement {
          public void accept(ICarElementVisitor visitor) {
                   visitor.visit(this);
          }
}

class Body implements ICarElement {
          public void accept(ICarElementVisitor visitor) {
                   visitor.visit(this);
          }
}

class Car implements ICarElement {
          ICarElement[] elements;

          public Car() {
                   // create new Array of elements
                   this.elements = new ICarElement[] { new Wheel("front left"),
                                      new Wheel("front right"), new Wheel("back left"),
                                      new Wheel("back right"), new Body(), new Engine() };
          }

          public void accept(ICarElementVisitor visitor) {
                   for (ICarElement elem : elements) {
                             elem.accept(visitor);
                   }
                   visitor.visit(this);
          }
}

class CarElementPrintVisitor implements ICarElementVisitor {
          public void visit(Wheel wheel) {
                   System.out.println("Visiting " + wheel.getName() + " wheel");
          }

          public void visit(Engine engine) {
                   System.out.println("Visiting engine");
          }

          public void visit(Body body) {
                   System.out.println("Visiting body");
          }

          public void visit(Car car) {
                   System.out.println("Visiting car");
          }
}

class CarElementDoVisitor implements ICarElementVisitor {
          public void visit(Wheel wheel) {
                   System.out.println("Kicking my " + wheel.getName() + " wheel");
          }

          public void visit(Engine engine) {
                   System.out.println("Starting my engine");
          }

          public void visit(Body body) {
                   System.out.println("Moving my body");
          }

          public void visit(Car car) {
                   System.out.println("Starting my car");
          }
}

public class VisitorExample {
          public static void main(String[] args) {
                   ICarElement car = new Car();
                   car.accept(new CarElementPrintVisitor());
                   car.accept(new CarElementDoVisitor());
          }
}

Visitor (recognizeable by two different abstract/interface types which has methods definied which takes each the other abstract/interface type; the one actually calls the method of the other and the other executes the desired strategy on it)


Book Review: Spring Start Here: Learn what you need and learn it well

  Spring Start Here: Learn what you need and learn it well by Laurentiu Spilca My rating: 5 of 5 stars This is an excellent book on gett...