Path: csiph.com!x330-a1.tempe.blueboxinc.net!usenet.pasdenom.info!weretis.net!feeder4.news.weretis.net!eternal-september.org!feeder.eternal-september.org!mx04.eternal-september.org!.POSTED!not-for-mail From: markspace <-@.> Newsgroups: comp.lang.java.programmer Subject: Re: Design Question Date: Sun, 18 Dec 2011 19:23:51 -0800 Organization: A noiseless patient Spider Lines: 131 Message-ID: References: Mime-Version: 1.0 Content-Type: text/plain; charset=ISO-8859-1; format=flowed Content-Transfer-Encoding: 7bit Injection-Date: Mon, 19 Dec 2011 03:23:54 +0000 (UTC) Injection-Info: mx04.eternal-september.org; posting-host="XjIWM99mD7Ijfdu600oVPA"; logging-data="28460"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX1/Fzakv76XBBFMOdVTPj2Ic8ChQrorEMv4=" User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:8.0) Gecko/20111105 Thunderbird/8.0 In-Reply-To: Cancel-Lock: sha1:NyOygP6RWKDpHRN9nb0346edEsc= Xref: x330-a1.tempe.blueboxinc.net comp.lang.java.programmer:10860 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.