Anyone who has plumbed through a Servlet container like Tomcat will recognize the “pattern” above. Not just Servlet containers, many popular Java service provider frameworks implement services the same way.
I end up explaining this “pattern” to people all the time, but I can’t find a specific pattern names to which to them. Then again, it really is about using interfaces and abstract classes properly, so it is more like a feature of the language than a true pattern. Some of the .Net pattern people reefer to something similar as the Provider Pattern.
What’s in a Name?
Unless someone can tell me the real name of the pattern, I am going to call it “Bob.” Now people will just have to know that I want the service designed like “Bob,” I mean like this.
How the Pattern Works
You have a ServiceInterface that works on a ResourceInterface. For example,
- Service Interface: Servlet
- Resource Interfaces: ServletRequest and ServletResponse
Each subclass of the ServiceInterface also subclasses the resources, so these extend in parallel. For example:
- Service: HttpServlet
- Resource: HttpServletRequest and HttpServletResponse
However, clients of the Service, typically only know about the base Service and Resources classes. Only for special clients do they care about the extended HTTP behavior and they can test the Service and Resources by instancesof.
In some cases, you may even apply multiple extension interfaces to a Service or a Resource for client to access multiple sets of extended features.
Where the Pattern Comes From
For Java services, the evolution starts simply from:
Interface and Implementation
- Define your service with an interface
- Provide a Basic implementation of the service that implements the interface
Interface, to Abstract, to Implementation
After you implement a few variations of your service, you find that you have a lot of common code that you want to share. Typically, a majority of the services are more similar than different. So you implement all of the common functionality in an abstract class.
You refactor your Basic implementation to extend the AbstractService.
Extend, Aggregate, or Only Implement
Now for each subsequent service you implement, you have the option to:
- Make a service that is pretty routine and simply extends the abstract service class and adds what few things are unique, OR
- Implement that interface, but because your service is so atypical, you implement your own Service from scratch, OR
- Somewhere in the middle, you implement you own service but aggregate an internal instance of the Basic Service Inmplementation to leverage some common functionality.
You can see this with the HttpServlet service. Like most services, the Servlet works as a stateless (unless you are doing something screwy) service that passes what is specific to the request in a set of messages. In the case of the HttpServlet, you get HttpServletRequests and HttpServletResponse (among other message objects).