Reputation: 2860
For a school project, I need to write a simple Server in Java that continuously listens on an incoming directory and moves files from this directory to some place else. The server needs to log info and error messages, so I thought I could use the Proxy pattern for this. Thus, I created the following ServerInterface:
public interface ServerInterface extends Runnable {
public void initialize(String repPath, ExecutorInterface executor, File propertiesFile) throws ServerInitException;
public void run();
public void terminate();
public void updateHTML();
public File[] scanIncomingDir();
public List<DatasetAttributes> moveIncomingFilesIfComplete(File[] incomingFiles);
}
Then I've created an implementation Server
representing the real object and a class ProxyServer
representing the proxy. The Server
furthermore has a factory method that creates a ProxyServer
object but returns it as a ServerInterface
.
The run
-method on the proxy-object looks like this:
@Override
public void run(){
log(LogLevels.INFO, "server is running ...");
while( !stopped ){
try {
File[] incomingContent = scanIncomingDir();
moveIncomingFilesIfComplete(incomingContent);
updateHTML();
pause();
} catch (Exception e) {
logger.logException(e, new Timestamp(timestampProvider.getTimestamp()));
pause();
}
}
log(LogLevels.INFO, "server stopped");
}
The functions that are called within the try
statement simply log something and then propagate the call to the real object. So far, so good. But now that I've implemented the run
-method this way in the proxy object, the run
-method in the real object becomes obsolete and thus, is just empty (same goes for the terminate
-method).
So I ask my-self: is that ok? Is that the way the proxy pattern should be implemented?
The way I see it, I'm mixing up "real" and "proxy"-behaviour ... Normally, the real-server should be "stuck" in the while-loop and not the proxy-server, right? I tried to avoid mixing this up, but neither approaches were satisfying:
I could implement the run
-method in the real object and then hand over the proxy object to the real object in order to still be able to log during the while-loop. But then the real object would do some logging, which is I tried to avoid by writing a proxy in the first place.
I could say, only Proxy-Server is Runnable
, thus deleting run
and terminate
from the Interface, but this would break up the Proxy pattern.
Should I may be use another design? Or I am seeing a problem where there is none?
Upvotes: 4
Views: 758
Reputation: 1881
You can make your proxy aware of the real object. Basically your proxy will delegate the call to run method to the real implementation.
Before the delegation, the proxy first logs the startup. After delegation, the proxy logs the "shutdown":
// Snapshot from what should look like the run method implementation
// in your proxy.
public ServerInterfaceProxy(ServerInterface target){
this.proxiedTarget = target;
}
public void run(){
log(LogLevels.INFO, "server is running ...");
this.proxiedTarget.run();
log(LogLevels.INFO, "server is running ...");
}
This implementation can also be perceived as a Decorator pattern implementation. IMHO, I believe that to some extent (when it comes to implementation) Proxy and Decorator are equivalent : Both intercept/capture behavior of a target.
Upvotes: 0
Reputation: 28766
You're definitely thinking in the right way. You've hit upon an interesting notion.
Features like logging, as you've described, are an example of what we call cross-cutting concerns in Aspect Oriented programming.
. . therefore, they have the tendency to break object oriented programming. What does this mean?
Enter Aspect Oriented Programming
This is the reason we have AOP - it exists to modularize and encapsulate these cross-cutting concerns. It works as follows:
Ways we can "weave" in a requirement with AOP
The latter two options are supported in AspectJ.
In Conclusion:
It sounds as though you're moving towards Aspect Oriented Programming (AOP), so please check this out. Note also that the Spring Framework has a lot of features to simplify the application of AOP, though in your case, given this is a school assignment, its probably better to delve into the core concepts behind AOP itself.
NB: If you're building a production-grade server, logging may be a full-blown feature, and thus worth using AOP. . in other cases its probably simple enough to just in-line.
Upvotes: 2
Reputation: 10707
You should use Observer pattern in this case:
The observer pattern is a software design pattern in which an object, called the subject, maintains a list of its dependents, called observers, and notifies them automatically of any state changes, usually by calling one of their methods.
Your Observable
will observe changes in directory, by time pooling, or as already was suggested here, with WatchService
. Changes of directory will notify Observer which will take action of moving files. Both Observable and Observer should log their actions.
You shold also know that Observer pattern became a part of Java JDK by implementing java.util.Observable
and java.util.Observer
.
Upvotes: 0