aspose file tools*
The moose likes Developer Certification (SCJD/OCMJD) and the fly likes Demistifying the OCMJD Certification paper - OKButtonListener Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login
JavaRanch » Java Forums » Certification » Developer Certification (SCJD/OCMJD)
Bookmark "Demistifying the OCMJD Certification paper - OKButtonListener" Watch "Demistifying the OCMJD Certification paper - OKButtonListener" New topic
Author

Demistifying the OCMJD Certification paper - OKButtonListener

Sean Keane
Ranch Hand

Joined: Nov 03, 2010
Posts: 581

Hi folks. I've been taking a read through Roberto Perillo's Demistifying the OCMJD Certification paper. First off it is great resource and many thanks to Mr. Perillo for spending the time to create it . Now I have a question about the OKButtonListener class (page 21) and its concrete subclasses that I was wondering if anyone could help me with?

My question is about the use of the getManager() method in the OKButtonListener:

This method is called by concrete subclasses in order to get their LaunchManager, as follows:

The purpose of doing this is to get information about the particular launch configuration in order to store the settings in a properties files - i.e. there will be different settings to store for "stand alone mode" and "network mode".

Is this an ideal solution, where you are returning an interface where you will always have to cast it to the concrete type in order to carry out the action you require to carry out?

Is there a way of refactoring this to avoid the need to cast the return type?

Lastly to Roberto, if he is out there - did you use this solution with casting in your actual assignment that you submitted?


Cheers, Sean.


SCJP (1.4 | 5.0), OCJP (6.0), OCMJD
Roel De Nijs
Bartender

Joined: Jul 19, 2004
Posts: 5265
    
  13

In my daily job we try to avoid casts as much as possible, because they clutter up your code if you want to be on the safe side (you have to first use instanceof operator prior to casting the object). Of course there are situations where you don't have another option than using a cast (e.g. when you work with some old java library).

When you develop new code (using jdk 1.5 or above) you have some alternatives to avoid this cast:
  • covariant return


  • using generics



  • Hope it helps!


    SCJA, SCJP (1.4 | 5.0 | 6.0), SCJD
    http://www.javaroe.be/
    Roberto Perillo
    Bartender

    Joined: Dec 28, 2007
    Posts: 2265
        
        3

    Howdy, Sean!

    Well champ, in the case that you mentioned, if everything is coded as mentioned in the paper, it will alwyas be safe to cast to StandaloneLaunchManager because that is certainly the object's dynamic type (the static type is LaunchManager).

    I wrote this paper after a lot of time spent here, always thinking about a better way to design the assignment and code the project. So, in my solution, for each button, I had a class that implemented ActionListener directly. But it is certainly an effective way to do things, why not? But maybe we could think about a solution with generics in order to avoid the casting. I'll try to do that in the next days.


    Cheers, Bob "John Lennon" Perillo
    SCJP, SCWCD, SCJD, SCBCD - Daileon: A Tool for Enabling Domain Annotations
    Sean Keane
    Ranch Hand

    Joined: Nov 03, 2010
    Posts: 581

    Hi guys. I think the solution to avoiding the casts is quite simple. Store the concrete implementation of the LaunchManager as a member variable of the implementation of the OKButtonListener class that it relates to i.e. store the instance of StandaloneLaunchManager that is passed into the constructor of StandaloneOKButtonListener as a member variable of the StandaloneOKButtonListener class itself.

    If I am reading the intention of Roberto's design correctly, then actionPerformed method of the OKButtonListener is operating as a Template Method where the operation to save the properties is delegated off the to particular class that implements OKButtonListener. The implication being that the subclass knows best how to save the properties associated with its LaunchManager.

    Based on this logic it seems quite simple to me. Since the subclass of OKButtonListener needs to know about the properties associated with its LaunchManager, then it should have a handle to its LaunchManager. Storing it as a member variable provides the subclass with this handle.

    How does this sound?


    Roberto Perillo
    Bartender

    Joined: Dec 28, 2007
    Posts: 2265
        
        3

    Howdy, Sean.

    So, the only difference is that, instead of sending the LaunchManager object to the super class, you are keeping it in the subclass. Well, when I created this code, I thought about sending it to the super class because, since the actionPerformed method is a template method and it is in the super class, you get the Services instance, call LaunchManager's closeWindow() method, then instantiate the MainWindow object, passing the Services instance. So the LaunchManager object has to stay in the super class. Another possible way is to still send the LaunchManager object to the super class and keep a local reference to it, which would be a mix of what you and I did. But I still think that a solution with generics would be more fancy so I'll think about something in the next days.
    Sean Keane
    Ranch Hand

    Joined: Nov 03, 2010
    Posts: 581

    Hi Reberto, yep, that's the only difference - I stored the reference in the subclass. But I couldn't see a way around not storing the reference in the subclass.
    Roberto Perillo wrote:So the LaunchManager object has to stay in the super class.

    But what if you did as I suggested in the code comment and made the getManager method abstract in the super class? Then this would just be another Template Method like the saveProperties method and your actionPerformed method in the super class would still function. Does that sound correct?
    Roberto Perillo wrote:Another possible way is to still send the LaunchManager object to the super class and keep a local reference to it, which would be a mix of what you and I did.

    Yep, that is what I did initially. But I thought it looked a bit odd so I removed the reference from the super class. If the super class needs access to the LaunchManager I think I would go with an abstract method in the super class.
    Roberto Perillo wrote:But I still think that a solution with generics would be more fancy so I'll think about something in the next days.

    This would be interesting. On the face of it, I can't see how generics will let you store the reference in the super class as the base type and still allow subclasses to access the concrete subtype.
    Roel De Nijs
    Bartender

    Joined: Jul 19, 2004
    Posts: 5265
        
      13

    I just had a glance to Roberto's paper regarding this question and I was making following thought(s). Why would you need a seperate OKButtonListener for standalone-mode and network-mode? Seems a bit strange to me. I would design that part of the code as follows:



    This approach makes more sense to me, because all your logic with regard to a LaunchManager is in 1 class (hierarchy) and not in a few classes (the StandaloneOKButtonListener contains also some logic to save the properties of the StandaloneLaunchManager). And you need fewer classes, which mean fewer classes to maintain
    But this was just my initial thought when I looked at the code mentioned in the OP. Maybe it's mentioned in the text you opted for this approach for some reasons I don't know, because I didn't have read the text (if the design is good, it's self-explanatory and no additional comments are needed).

    just my 2 cents.
    Kind regards,
    Roel
    Roberto Perillo
    Bartender

    Joined: Dec 28, 2007
    Posts: 2265
        
        3

    The idea of the these interfaces that extend LaunchManager is to only provide access to the text fields where the user provides data, and they are more likely to be implemented by classes that extend JFrame, or that are the windows so to speak, and thus, they are view components. Although it looks simpler, I don't think they are the right place to instantiate the Data and business objects and to save the properties provided by the user. These tasks are supposed to be performed in Controllers, which are the ActionListeners. So, in my opinion, it is still better to keep separate ActionListener objects, one for each mode.

    @Sean: I'll try to think about something in the next days regarding generics... but, if everything is coded as mentioned in the paper, it will always be safe to cast to the dynamic type that corresponds to the way the application was started. At a first glance, keeping the business object in the sub class has the same effect. Only the getManager() method in the OKButtonListener class would have to be abstract and should be implemented in each sub class.
    Roel De Nijs
    Bartender

    Joined: Jul 19, 2004
    Posts: 5265
        
      13

    The idea of the these interfaces that extend LaunchManager is to only provide access to the text fields where the user provides data, and they are more likely to be implemented by classes that extend JFrame, or that are the windows so to speak, and thus, they are view components. Although it looks simpler, I don't think they are the right place to instantiate the Data and business objects and to save the properties provided by the user. These tasks are supposed to be performed in Controllers, which are the ActionListeners. So, in my opinion, it is still better to keep separate ActionListener objects, one for each mode.

    From that point of view I totally agree with you.

    In the end I would not use generics, but opt for the covariant return. It adds no complexity to your classes and you have the cast just in 1 place. You can simply use the getManager()-method without having to cast. It's my preferred solution.

    Stefan Neuhaus
    Greenhorn

    Joined: Nov 10, 2012
    Posts: 3

    Roberto Perillo wrote:The idea of the these interfaces that extend LaunchManager is to only provide access to the text fields where the user provides data [...].


    If this is the only reason, I would suggest another approach. One could make the configuration accessible through a generic method in the LaunchManager:



    Each LaunchManager implementation knows which Parameters he is able to provide and each OKButtonListener and the ServerOKButtonListener know which Parameters to request.

    By doing so you trade off the compile-time safety of your approach (which is somehow undercut due to the cast) against a less complex design: You can get rid of the interfaces StandaloneLaunchManager, ClientLaunchManager, and ServerLaunchManager.

    Both designs have their pros and cons.
     
    I agree. Here's the link: http://aspose.com/file-tools
     
    subject: Demistifying the OCMJD Certification paper - OKButtonListener