Path: csiph.com!x330-a1.tempe.blueboxinc.net!usenet.pasdenom.info!aioe.org!.POSTED!not-for-mail From: Novice Newsgroups: comp.lang.java.programmer Subject: Re: Design Question Date: Mon, 19 Dec 2011 13:26:29 +0000 (UTC) Organization: Your Company Lines: 157 Message-ID: References: NNTP-Posting-Host: yAGUs4XBtTVK1LRJtRfATw.user.speranza.aioe.org X-Complaints-To: abuse@aioe.org User-Agent: Xnews/5.04.25 X-Antivirus-Status: Clean X-Notice: Filtered by postfilter v. 0.8.2 X-Antivirus: avast! (VPS 111218-1, 2011-12-18), Outbound message Xref: x330-a1.tempe.blueboxinc.net comp.lang.java.programmer:10868 markspace <-@.> wrote in news:jcmaoa$rpc$1@dont-email.me: > On 12/18/2011 4:13 PM, Novice wrote: >> Am I right in thinking that I should actually have an abstract class, >> maybe called AbstractScore, and that it should have two subclasses, > >> Or is there a better way? > > > Generally, one wants to "prefer composition to inheritance." That is, > sub-classing (any object, abstract or otherwise(*)) should be > considered after trying to compose a class out of other classes seems > unsatisfactory. > > ((*) However if you must subclass, using an abstract class as the base > class is best.) > > In this case, composition might lead you to use two dialogs, each with > different behaviors. Both dialogs might have-a "score" which they > share. This is more MVC, where the dialogs (the view, the V part), > are separate from the model (the M part). Model here means your > program logic (the score from a game) and view means the GUI (or some > other "front end"). > > class MyInterumScoreDialog extends Dialog { > private int score; > ... > } > > class MyFinalScoreDialog extends Dialog { > private int score; > ... > } > > This allows you to have two objects, with different behavior, but > which also share a state (the score). The score here would probably > be injected with a setter method or with the object's constructor. > This is the nice part of composition, that it works well with > "dependency injection." > > > However, with a bit more reflection, you might decide that the two > dialogs above share a lot of things in common, and only differ > slightly in their behaviors. So you might want to combine them into > one object, if possible. The things that are different are the text > they display, the score itself, the label on the button, and the > action taken when the button is clicked. If these things could be > represented in an abstract way, we'd have a more concise way of > expressing what is we want, and an even more composed object. > > This type of operation is so common in GUIs (display a message, > collect a button press) that Swing devotes a whole slew of boilerplate > methods to it. > > > > Let's see if I can pick one out of that list that seems to fit... Well > the bit on "Customizing the Button Text" seems closest. > Unfortunately, they don't provide a way to abstract the action taken. > Here's the basic code from the tutorial which I've tweaked a bit. > > Object[] options = {"OK",}; > > int n = JOptionPane.showOptionDialog(frame, > "Your intermediate score is:\n"+score, > "Intermediate Score", > JOptionPane.DEFAULT_OPTION, > JOptionPane.QUESTION_MESSAGE, > null, //do not use a custom Icon > options, //the titles of buttons > options[0]); //default button title > > Just FYI, I didn't test or compile that code. Caveat emptor. > > So now what do we do about that action? Well we can just test a > return value, and take an appropriate action. We can do this inside a > "controller" (the C part of MVC), which would be some bit of code that > executes in response to a user action. In this case, probably > finishing a level activates the score dialog. > > public class MyGame { > > private int score; > private boolean gameOver; // == "score is final" when true > > ... > > void endLevel() { // called at the end of each level > // ... other end of level stuff here ... > > // display the score dialog > if( gameOver ) { > // display the final score, and exit > > ... JOptionPane.showOptionDialog( ... > System.exit(0); > } else { // intermediate score, display and keep going > > ... JOptionPane.showOptionDialog( ... > // just fall through, final score doesn't return > } > } > > ... > } > > Note that you'll have to change some of the code from the JOptionPane > exampled I showed for the final block of code. E.g., the text strings > that say "intermediate" should be changed to say "final". > > So this seems to separate concerns a bit more to me than inheritance, > or making a class with a special state (which seems to me to mix a bit > the "model" (game code) with the "view" (GUI)) in an odd fashion. > > The way it's done here, the GUI is pretty ignorant of what our game's > state is (we just pass it strings, it has no idea what's going on) and > we've eliminated some complexity (that complexity being a special > combined model/GUI class that needs to hold the "final score" state) > by using a standard, built-in class (or method, in this case) that > gives us the behavior we need. > > Sometimes, OO makes sense, but sometimes procedural is better. > Especially in "terminal" elements of a design (that is, the leaves or > lowest elements of your design). At some point you have to stop > making objects and just make the code actually do something. When to > do that is a matter of some experience, but also "how easy is this to > do?" Once it's easy enough, just do it. > > In this case, I found a standard method that would do what I wanted > with only a little manipulation, so I took that way out. Once my > design reach a point that I could call that method, rather than > decompose further, or make more objects, I just yell "done!" and write > the method, and move on to the next design requirement. > Thanks VERY much markspace for taking me through that thought process and helping me understanding what a more experienced designer would do in this situation. As it turns out, I thought of a better way to handle the score as I was composing my question - to simply show the current score on the main game window itself throughout the game rather than displaying a dialog on request - but I kept writing the question anyway to get a handle on the thought process that I should be going through with respect to the two very similar dialogs. Therefore, my effort in asking the question and yours in answering it were NOT wasted and I've learned a better way to think of these matters. So thanks again, markspace! -- Rhino -- Novice