Hi there!
Today i'm gonna show you the router pattern i wrote myself in action. The Router design pattern is a very useful
programming design pattern whenever
you need to be able to send objects or messages between instances over the application.
The example i will provide is a nice way to show it how it
could looks like.
You can always come back here, take it, adapt it and use it in your applictions as you may need. So be sure you bookmark it or join the group here on the right side of this post subscribing it.
If you use it anywhere, please come back and give me a feedback. It would be nice to have more real use cases.
First of all, let's take a look at the UML diagram of it. After that we will take the analogy for our example.
The UML Diagram of the Router Pattern
Pay close
attention, because once you understand that, everything will become
clear and simple to understand. That's the reason I'm putting always the
UML first. That way you'll get an eye for it with the time.
The example
In
our example we will see, how we could create clients that listen to server responses. The servers are lazy instantiated and are created on demand.
Response and Request Interfaces
Those interfaces defines a contract to be used to design which type the client will use to send requests and receive responses. Let's take a closer look to it:
public interface Response < T > {
T getResponse();
void setResponse(T value);
}
public interface Request < T > {
T getRequest();
void setRequest(T value);
}
Client and Server Interfaces
Those interfaces defines a contract to be used while implementing concrete clients and servers. It uses either the Response or the Request depending on the what you are implementing:
public interface Client {
< T extends Response < ? > > void onServerResponse(T response);
}
public interface Server {
< T extends Request < ? > > void onClientRequest(T request, Client client);
}
Routable interface and Router class
The routable defines the contract for the router. The router itself is designed as a singleton and can be accessed and used everywhere in the application sending and receiving messages or objects. In this implementation the servers are lazy implemented and created on demand. For sure you may adapt it to your needs. Feel free to do it and give me feedback of the usage of it in your applications.
public interface Routable {
public < T extends Client > void registerClient(T clientImpl);
public void registerServer(Class < ? extends Server > serverImpl);
public < T extends Request < ? > > void routeClientToServer(Class < ? extends Client > clientImpl, Class < ? extends Server > serverImpl, T request);
public void removeClient(Class < ? > serverClass);
public void removeAllClients();
public void removeServer(Class < ? > clientClass);
public void removeAllServers();
public boolean isRegistered(Class < ? > clazz);
}
public class Router implements Routable {
private Map < String, Client > clients = new HashMap < String, Client > ();
// using sets to avoid duplicates
public Set < Class < ? extends Client > > clientSet = new HashSet < Class < ? extends Client > > ();
public Set < Class < ? extends Server > > serverSet = new HashSet < Class < ? extends Server > > ();
private static final Router ROUTER = new Router();
private Router() {
// singleton - can be accessed anywhere in the application
}
public static Router turnOn() {
return ROUTER;
}
public < T extends Request < ? > > void routeClientToServer(Class < ? extends Client > clientImpl, Class < ? extends Server > serverImpl, T request) {
doNotAllowNullValue(clientImpl);
doNotAllowNullValue(serverImpl);
doNotAllowNullValue(request);
doNotAllowUnregisteredNullValue(isRegistered(clientImpl));
// just to ensure that the server implementation exits already
doNotAllowUnregisteredNullValue(isRegistered(serverImpl));
// as we now know that the server implementation exists,
// we just create a lazy instance over reflection on demand
try {
serverImpl.newInstance().onClientRequest(request, clients.get(clientImpl.getName()));
} catch (InstantiationException e) {
// we shall never run into this situation, except if the user does NOT define
// a default constructor in any of the concrete implementation of Server as per
// convention.
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
public void removeServer(Class < ? > serverClass) {
serverSet.remove(serverClass);
}
public void removeAllServers() {
serverSet.clear();
}
public void removeClient(Class < ? > clientclass) {
clients.remove(clientclass.getName());
clientSet.remove(clientclass);
}
public void removeAllClients() {
clients.clear();
}
public boolean isRegistered(Class < ? > clazz) {
boolean result = false;
boolean searchBreak = false;
Iterator < Class < ? extends Client > > iterator = clientSet.iterator();
while (iterator.hasNext()) {
Class < ? extends Client > next = iterator.next();
// note: we can't use equalsIgnoreCase here
if (next.getName().equals(clazz.getName())) {
result = true;
searchBreak = true;
break;
}
}
if (!searchBreak) {
Iterator < Class < ? extends Server > > it = serverSet.iterator();
while (it.hasNext()) {
Class < ? extends Server > next = it.next();
// note: we can't use equalsIgnoreCase here
if (next.getName().equals(clazz.getName())) {
result = true;
searchBreak = true;
break;
}
}
}
return result;
}
public < T extends Client > void registerClient(T clientImpl) {
doNotAllowNullValue(clientImpl);
clientSet.add((Class < ? extends Client > ) clientImpl.getClass());
clients.put(clientImpl.getClass().getName(), clientImpl);
}
public void registerServer(Class < ? extends Server > serverImpl) {
doNotAllowNullValue(serverImpl);
serverSet.add(serverImpl);
}
private void doNotAllowNullValue(Object toCheck) {
if (toCheck == null) {
final String msg = "You can't pass null to this method!";
throw new NullPointerException(msg);
}
}
private void doNotAllowUnregisteredNullValue(boolean isRegistered) {
if (!isRegistered) {
final String msg = "Either the client or the server was not registered in this router. Register it first!";
throw new IllegalArgumentException(msg);
}
}
}
Sample Implementation and Test
Now let's see how a real implementation could looks like and how it works in practise. First of all we are gonna define some responses and requests. Then we will create the clients and servers. Finally we will test it, by running a junit test to show it in action.
//SAMPLE CLIENT RESPONSE
public class ClientResponse implements Response < String > {
private String response;
public String getResponse() {return response;}
public void setResponse(String value) {response = value;}
}
//SAMPLE SERVER REQUEST
public class ServerRequest implements Request < String > {
String request;
public String getRequest() {return request;}
public void setRequest(String value) {request = value;}
}
// SAMPLE CLIENT IMPL
public class ClientImpl implements Client {
public < T extends Response < ? > > void onServerResponse(T response) {
System.out.println(response.getResponse());
}
}
//SAMPLE SERVER IMPL
public class ServerImpl implements Server {
public < T extends Request < ? > > void onClientRequest(T request, Client client) {
// handle request and depending on it create response
ClientResponse clientResponse = new ClientResponse();
clientResponse.setResponse("Server is sending a response to client...");
// route response back to client immediately or whenever you want
client.onServerResponse(clientResponse);
}
}
public class RouterTest {
@Test
public void testRouter() {
Router.turnOn().registerClient(new ClientImpl());
// servers would be only referenced and lazy instantiated later
Router.turnOn().registerServer(ServerImpl.class);
System.out.println("Client is sending a request to server...");
ServerRequest request = new ServerRequest();
request.setRequest("Client is sending a request to server...");
Router.turnOn().routeClientToServer(ClientImpl.class, ServerImpl.class, request);
}
}
That's all! hope you like it! :)
😱👇 PROMOTIONAL DISCOUNT: BOOKS AND IPODS PRO 😱👇
Be sure to read, it will change your life!
This book is a must read - it will put you in another level! (Expert)
Write cleaner code and stand out!
This book is very practical, straightforward and to the point! Worth every penny!
Needless to say, these are top right?
😱👆 PROMOTIONAL DISCOUNT: BOOKS AND IPODS PRO 😱👆