1

How should Listeners etc be managed? I've found only examples with one button etc.

I can think of following options:

  1. Extra class for each - doesn't seem right, especially when items can be created dynamically
  2. Class for each group (such as form1, form2, controlButtonsOnLeft, controButtonsOnRight, mainMenu, userMenu, ...) where I'll check which button/component caused this (via getSource method for example)
  3. Some super (sized) controller, which will accept all user actions
  4. New anonymous class for each, which will call controller's method with parameters specifying details (probably enums)

And another question: I've found many examples for MVC, I was wondering what is better (or commonly used) for app. developed by 1 person (app will not be huge)?

A. Viewer sets listeners to controller (A1-3)

B. Controller calls viewer's methods, which accepts listener as parameter (methods addLoginSubmitListener, addControlBoldButtonListener etc)

All of above are possible to implement and so far I would choose B4. Meaning in Control I would do something like this:

...
viewer.addLoginButtonListener(new Listener()
{
  @Override
  public void actionPerformed(ActionEvent e) {
    ...
    someButtonsActionHandler(SomeButtonEnum, ActionEnum);
    ...
  }
});
...
private void LoginActionHandler(LoginElementsEnum elem, ActionEnum action)
{
  if (elem.equals(LOGINBUTTON)) {...}
  ...
}
...

This combines readable code (1 logic part at one place in code), doesnt create any unwanted redundant code, doesnt require any hardly-dynamic checks, is easily reusable and more. Can you confirm/comment this solution?

4
  • When using anonymous implementations for listeners, you later cannot remove them when disposing the object, which will eventually (and you will have those situations) cause memory leaks. Commented Oct 28, 2014 at 22:36
  • @alterfox:Thanks for pointing. Commented Oct 28, 2014 at 22:52
  • @alterfox:Isn't this handled by GC? Listener's list is the only reference for such anonymous listener and it will be emptied during component's disposing, right? Or perhaps I missunderstood. In such case I'll create a class for this and add one parameter for constructor, which will decide which method will handle it. [maybe there's better solution, this was first one that crossed my mind] Commented Oct 28, 2014 at 23:02
  • E.g. B starts listening to A. That means that B's listener is present in A's list of listeners. Later on, B gets disposed, and A keeps living on. The listener is a strong reference preventing GC from releasing B's resources, so it needs to be removed. This of course if the listener is not constructed as a weak listener, which a different topic. Commented Oct 28, 2014 at 23:27

1 Answer 1

1

To be honest the question comes down to a number of questions...

  • Do you want reusability?
  • Do you want configurability?
  • Are they self contained? That is, does it make sense for anybody else to listener to the component or need to modify the resulting action of the listener in the future?

Personally, I lean towards self containment. A single listener for a given action/task. This makes it easier to manage and change should I need to.

If I don't need reusability (of the listener) or configurability, then an anonymous inner class is generally a preferred choice. It hides the functionality and doesn't clutter the source code with small, once use classes. You should beware that it can make the source code difficult to read though. This of course assumes that the task is purpose built (its a single, isolated case). Normally, in these cases I will prefer to call other methods from the listener that actually do the work, this allows a certain amount of flexibility and extendability to the class. Too often you find yourself wanting to modify the behaviour of a component only to find that behaviour buried within an anonymous or private inner class...

If you want reusability and/or configurability - that is, the listener performs a common task which can be repeated throughout the program or over time via libraries, then you will need to provide dedicated classes for the task. Again, I'd favour a self contained solution, so any one listener does only one job, much easier to change a single listener then having to dig through a compound list of if-else statements :P

This could also be a series of abstract listeners, which can build functionality for like operations, deleting rows from a table for example...

You could considering something like the Action API (see How to Use Actions for more details), which are self contained units of work but which also carry configuration information with them. They are designed to work with buttons, such as JButtons and JMenuItems, but can also be used with key bindings, making them extremely versatile...

The second part of you question (about MVC) depends. I prefer to keep UI related functionality in the view and out of the controller as much as possible. Instead of allowing the controller to set listeners directly to components, I prefer to provide my own, dedicated, listener for the controller/view interaction, which notifies the controller of changes to the view that it might like to know about and visa versa.

Think about it this way. You might have a login controller and view, but the controller only cares about getting the credentials from the view and authenticating them when the view makes the request, it doesn't care how that request is made from the views perspective. This allows you to design different views for different circumstances, but so long as you maintain the contract between the view and the controller, it won't make any difference...But that's just me.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.