Home | Contact Us | FAQ | Search & Site Map | Link to Us
Sign In | Join | Other 45 Sites in Network
HomeAnnouncementsWhite Papers
Discussion GroupsFirst AidDatabasesJavaBeansGUIJava 3DVirtual MachineCORBASecurityToolsGeneral
Java DirectoryOpen Source ProjectsSample Book ChaptersUser GroupsWeb Resources
Related Topics
Databases.NETMore Topics ...

Java Forum / General / March 2008

Tip: Looking for answers? Try searching our database.

Action vs Controller

Thread view: 
Royan - 25 Mar 2008 16:22 GMT
This is a question on architecture.

In java we have two options on how to implement event handling
mechanism.
* First is to subclass AbstractAction, define all action handling
logic within this subclass and then initialize all GUI controls with
an object of this subclass or call setAction on controls.
* Second is to implement MVC pattern and put all action logic and
*any* other handling event logic into the Controller class.

As you can see the only difference between option #1 and option #2 is
that Controller is more versatile that AbstractAction subClass.

I would like to ask your opinion on which option do you think is
better for a generic GUI application? I understand that the decision
highly depends on the exact task, but imagine your task is to develop
quite a small GUI app with just one static JMenuBar and a few GUI
controls on the main JFrame window. Also you would probably want to
develop further in the future.

-R.
Mark Space - 25 Mar 2008 18:07 GMT
> In java we have two options on how to implement event handling
> mechanism.
> * First is to subclass AbstractAction, define all action handling
> logic within this subclass and then initialize all GUI controls with
> an object of this subclass or call setAction on controls.

I've never seen any designs actually use this.  Not that I'm an expert
or anything.

Everything in the GUI world I've seen uses MVC or a related pattern.  It
might be best to stick to what another programmer is going to familiar
with and able to maintain.  "Exit strategy" and all that. Plus MVC is
portable, whereas Swing's action system may not work anywhere else if
you have to port your application.

If you'd like to explain what you think the advantages of using Actions
are over MVC and event listeners, I'd like to hear it.  Just looking at
it, AbstractAction inherits several fields and these look like they
would take up a fair memory footprint if there were many of them, which
there might be in a real GUI design.  Event listeners seem like they
might be somewhat lighter weight.

If you are looking for alternatives to MVC, check out Presenter First:

<http://en.wikipedia.org/wiki/Presenter_First>

The links at the end of that article are great.  Don't miss the PDF one
by the Atomic Object folks, but there is also an excellent video by
Brian Marick which gives a concrete (if simple) example in Java.  It's
much better than designs I've seen posted here involving lots of
Callables everywhere (which would be very heavyweight).
Stefan Ram - 25 Mar 2008 18:49 GMT
>* Second is to implement MVC pattern and put all action logic and
>*any* other handling event logic into the Controller class.

 In Java, often, a UI object is used instead of MVC.

     »The first Swing prototype followed a traditional MVC [...]
     We quickly discovered that this split didn't work well [...]
     So we collapsed these two entities into a single UI object [...]«

http://java.sun.com/products/jfc/tsc/articles/architecture/index.html

 In my own GUI applications, I am now using objects I call
 »components«. By coincidence, these components often indeed
 also are objects of a subclass of »javax.swing.JComponent«.

 (The rest of this post contains my own ideas about how I plan
 to construct my GUI applications. It might not be directly
 related to your question.)

 Each component can play all three rôles, i.e., model, view and
 controller.

 This sound like a big lump (i.e., bad style), but because each
 component has a clearly restricted responsibility, it will not
 get so large that this becomes a problem.

 »Model« here means only »application« model - any large
 calculation or data services are rolled out into service
 objectes (akin to a »domain model« or »implementation layer«).

 The application then is a tree of components, which only
 communicate via the tree connections.

 A component is an object controlling an area of a
 graphical user interface, like a command button or a window.
 (A degenerate component might also be an »invisible«
 component, i.e., a simple object.)

 An application usually has multiple components, often nested in
 the form of a tree.

 A window (which is a component), for example, might have an
 upper part with a list (which is a component) and a lower part
 with a log console (which is a component).

                     window
                    component
                       /\
                      /  \
                     /    \
                    /      \
                   /        \
                table     console
              component  component

      .---------------------------------.
      | window component                |
      | .-----------------------------. |
      | | table component             | |
      | |                             | |
      | |                             | |
      | |                             | |
      | '-----------------------------' |
      | .-----------------------------. |
      | | console component           | |
      | |                             | |
      | |                             | |
      | |                             | |
      | '-----------------------------' |
      '---------------------------------'

 Now, for example, consider the question: How does the table
 component request some text to be logged onto the console
 component?

 I do not want the table component to be aware of the console
 component. This would make it more difficult to reuse the
 table component in other contexts without a console component
 or to add or remove the table component or the console
 component independently of other components. (If you do not
 accept this reason, I also might refer to Demeter's law.)

 So, instead of directly accessing the console component, the
 table component "escalates" a log-report to the window
 component, which is its container. The window component then
 knows that it has a "log-report-handler" (i.e., the console
 component), and then delegates the log-request to the console
 component.

 Thus, the application component structure I made up recently is
 to build an application as a tree of components which obey
 Demeter's law and therefore only communicate via the /edges/
 of this component tree, i.e., each component communicates only
 with its direct container or one of its direct containees.

 A common special case are several components sharing a single
 model. Then, I want a common container component of these two
 components to be (or hold) the model. For example,

                     window (and model for "view 0" and "view 1")
                       /\
                      /  \
                     /    \
                    /      \
                   /        \
                view 0    view 1

      .---------------------------------.
      | window                          |
      | .-----------------------------. |
      | | view 0                      | |
      | |                             | |
      | |                             | |
      | |                             | |
      | '-----------------------------' |
      | .-----------------------------. |
      | | view 1                      | |
      | |                             | |
      | |                             | |
      | |                             | |
      | '-----------------------------' |
      '---------------------------------'

 Here, the window doubles as the model for its subcomponents,
 when they both need to refer to common data. (The observer
 relation might hold between any two components of an application,
 but has to be initiated via the edges of the tree.)

 The layout of an application might be changed at runtime by
 adding components to a container component. When this happens,
 some requirements will be checked: A certain container might
 only accept components implementing certain operations and the
 components might require its container to implement certain
 models for it.

 The tree structure means that each component (except the root
 component) has a single container component. This container
 component and the contained components (the »containees« of a
 component) represents the rest of the application to the
 contained component. So, by Demeter's Law, each component can
 only see one step in each direction.

 Whenever a component needs something to be done it can not do
 itself, it will request this from its direct container or from
 one of its containees.

 When a container receives a request from one of its directly
 contained subcomponents (i.e., from one of its containees), it
 might handle it or it might delegate it to another of its
 containees or its container (which I call »escalation«).

 When the root component receives a request it can not handle,
 it might report this as an error or silently drop the request,
 depending on what is most useful or appropriate in this
 application. (For example, when the »console component« is
 removed from the above application example,
 console-log-requests could be dropped silently, so the
 application will still run, but not have a console anymore.
 Or, the root component might hold a »console model« and add
 the messages to this model, so that they will all become
 visible when a console component is added again.)

 A component deep down in the tree might need to know the
 »current directory« of the application, so it will ask its
 container:

this.container.getEnv( "cd" );

 If the container does not have an environment variable »cd«,
 it will escalate the request to its own container:

Object getEnv( name )
{ if( this.env.contains( name ))return this.env.get( name );
 else return this.container.getEnv( name ); }

 Or, if a component does not have an own environment storage
 itself, it will immediatly escalate:

Object getEnv( name )
{ return this.container.getEnv( name ); }


Free Magazines

Get these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...

Oracle MagazineNetwork ComputingComputer WorldBio-IT WorldeWeekInformation WeekInfosecurity
 
Sign In
Join
My Latest Posts
My Monitored Threads
My Blog
My Photo Gallery
My Profile
My Homepage

Start New Thread
Enable EMail Alerts
Rate this Thread



©2008 Advenet LLC   Privacy Policy - Terms of Use
This website includes both content owned or controlled by Advenet as well as content owned or controlled by third parties.