From: Stefan F. <ste...@we...> - 2012-07-11 22:06:13
|
After the recent discussion I have finalized the Observer Interface. Related to this I present the Formatter (Abstract) Class that allows for different type of output from the identical Observable object. As usual comments are very welcome, as things can still be changed easily. Stefan *** Observer I took two major decisions that (on a first glance) limits the flexibility, however simplifies the structure. 1. Each observer is only allowed to observe one Observable (reminder: this is either a State or a Model). However an observable can have many observers (so it is a n:1 relation). 2. The data transferred is always a String. However this makes the Observer interface straightforward. There is only ... (public) void update(String text); ... one method with one argument containing the updated data from the observed Observable. This is called only once per ChangeSet activity (committing a new, undo, redo), and only if the Observable is changed by the ChangeSet(s) executed. * Usage: Adding an observer to an observable uses the following method: observable.addObserver(observer); It is possible to remove it: observable.removeObserver(observer); or to get a set with all attached observers observable.getObservers() * Remark: The two assumptions above are not as restrictive as it might appear: 1. It is easy to build a Class that contains several Observers as inner classes that observe multiple Observable. (Similar to Listeners in Swing). 2. It is possible that the String could contain XML, Json or another serialized representation of a more complex data structure. As long as no true client/server separation is done, direct callbacks are possible (and later one could still add some RMI technology). *** Formatter A class that extends the abstract Formatter class can act as a wrapper around an Observable to change the output text specific for different observers. Usually the text delivered to the update method of the observers is the one defined by the observerText() method of the Observable. A Formatter now allows to * Example: Share Portfolio Assume that you have a Model that represents the SharePortfolio of a Player (labelled CertificateModel). Now there could be two Observers in the GUI for that SharePortfolio: One could display the total percentage of the shares for one company (e.g. 40%, labelled percentViewer), whereas the other (called toolTipViewer) displays the exact compositon (20%P+1*10%+2*5%). To achieve this one creates a Formatter<CertificateModel> that take the CertificateModel as one argument to its constructor and the required type of output as the other argument (e.g. verbose=true/false). Then the Observer would not be added to the Observable directly, but to the Formatter objects, that wrap the Observable inside: detailedCertificates.addObserver(toolTipViewer) percentageCertificates.addObserver(percentViewer) * Another Example: BooleanState As Unit Test I have defined a simple Formatter for a BooleanState that instead the default text ("true" versus "false") simply delivers an alternative text representation ("yes" versus "no") * Implementation / Usage Again it is pretty simple: There is the abstract method observerText which has to be overwritten, e.g. in the case of BooleanState above: @Override public String observerText() { if (state.value()) { return "yes"; } else { return "no"; } } *** Current state of implementation Both Observer and Formatter are fully implemented and have unit tests attached. |