Encapsulating Remote Calls in a Faade
The Façade pattern is one of the software patterns described in the famed book Design Patterns: Elements of Reusable Object-Oriented Software by Gamma, Helm, Johnson, and Vlissides. This book defines the façade software pattern as a way of providing a higher-level interface to make a subsystem easier to use. In our case we want to encapsulate all of the RPC logic into a class that provides a simple interface in an effort to achieve the following:
Reduce complexity by reducing the number of classes we need to interact with.
Promote weak coupling, allowing us to alter the underlying RPC mechanism without affecting the client.
We all like reduced complexity, since easier is almost always better, so it is not hard to understand the motivation for wanting the first bullet point. We will realize this by creating a new class named ServerService with one method for each remote method plus a single getInstance() method.
package org.gwtbook.client;
1.2508
1.2509 public class ServerService
1.2511 public static ServerService getInstance();
1.2512 public void getStatusData (AsyncCallback callback);
This class follows the Singleton software pattern, providing a single static method to retrieve an instance of the ServerService class. From this instance, we have provided a getStatusData() method to call the remote service. It may be tempting to do away with the getInstance() method and just make the remote method call static, but this isn't a good idea. This would reduce the flexibility of the class and make it more difficult to do things such as allowing multiple instances to be created. It is one of those things where we need to make the code a little more verbose to make future maintenance easier.
With the interface for the service class defined, we now need to implement the RPC service it will provide. In our case our needs are rather simplistic, we only have a single endpoint, or service URL to call on the server, and we only have one method. So for us the implementation is rather straightforward.
Listing 11.5 The service façade
1.2514 package org.gwtbook.client;
1.2515
1.2516 import com.google.gwt.core.client.GWT;
1.2517 import com.google.gwt.user.client.rpc.AsyncCallback;
1.2518 import com.google.gwt.user.client.rpc.ServiceDefTarget;
1.2519
1.2520 public class ServerService {
1.2521
1.2522 private static ServerService instance;
1.2523 private ServerStatusServiceAsync proxy;
1.2524
1.2525 private ServerService() {
1.2526 proxy = (ServerStatusServiceAsync)
1.2527 GWT.create(ServerStatusService.class);
1.2528 ((ServiceDefTarget) proxy).setServiceEntryPoint(
1.2529 GWT.getModuleBaseURL() + "server-status");
1.2531
1.2532 public static ServerService getInstance() {
1.2534 instance = new ServerService();
1.2536 return instance;
1.2538
1.2539 public void getStatusData(AsyncCallback callback) {
1.2540 proxy.getStatusData(callback);
In our implementation, we have made the constructor private, allowing only the ServerService class to create an instance of itself. So what happens is that when getInstance() is called it will create a new instance of the ServerService class only if one has not been created. This ensures that there will only ever be one instance of this class. When the ServerService class is instantiated it creates the proxy instance that will be needed to call the server. When the getStatusData() method is finally called the proxy object will have already been created and it can simply pass the callback object to the proxy.
With this we have also effectively met our initial goals for using a façade. First we have reduced the complexity of the ServerStatusComponent class because it no longer needs to deal with any of the underlying RPC code, including the creation of a proxy object and needed to specify an endpoint. We have also decoupled the calling class from the actual RPC implementation. So we could potentially replace the GWT-RPC call with some other RPC mechanism such as XML-RPC and we can do this without having to change any code in the ServerStatusComponent. We can do this only because we have completely delegated the RPC responsibility to the ServerService class.
Now that we have the façade class implemented, we can write the rest of the code for the ServerStatusComponent. We do so by using the Command software pattern to provide some future flexibility.
Post a comment