I am task to do a simple order system. I want the JLabel (Amount: $0.00) show the corresponding amount on what the user picks for his burger and condiments. For example, if the user click on beef, the label will change into "Amount: $4.00", and when he choose a condiment, it will add $0.50 to the total based on how many condiments he picks and vice versa. Also, when the user unchecks a condiment (JCheckBox), it will deduct $0.50 dollars to the total.
My code for beef JRadioButton:
private void beef_radioBtnActionPerformed(java.awt.event.ActionEvent evt) {
total_amount.setText("Amount: $4.00");
ketchup_Checkbox.setEnabled(true);
mustard_Checkbox.setEnabled(true);
pickles_Checkbox.setEnabled(true);
}
Code for ketchup JCheckBox:
private void ketchup_CheckboxActionPerformed(java.awt.event.ActionEvent evt) {
float condiments_amount = (float) 0.50;
float beef_amount = (float) 4.00;
float total;
if (beef_radioBtn.isSelected()){
total = beef_amount + condiments_amount;
total_amount.setText("Amount: $" + decimal.format(total));
if (!ketchup_Checkbox.isSelected()){
total_amount.setText("Amount: $" + decimal.format(4.50 - condiments_amount));
}
else if (mustard_Checkbox.isSelected()){
total_amount.setText("Amount: $" + decimal.format(4.50 + condiments_amount));
}
else if (pickles_Checkbox.isSelected()){
total_amount.setText("Amount: $" + decimal.format(4.50 + condiments_amount));
}
}
}

Okay, buckle up, this is going to be a bit of ride.
One of the most powerful concepts you have available to you is the concept of "model". A model is just something that "models" something and is a way to seperate different areas of your program. So a model, models the data (think of it like a container) and the view will then use those models to format the data to the user (separation of concerns). A model may also contain business logic or perform calculations depending on its requirements.
The allows you to centralise concepts so you don't end up repeating yourself or forgetting to do things. It's also a way to change how parts of the program work, also known as "delegation"
Starting point, some interfaces
Well, that's a lot of "blah", so let's get started. I prefer to use
interfaces to describe things, it provides a lot of freedom, as you can put differentinterfaces together to suit different requirements.The Menu
Okay, simple concept, this will be a list of items which are available to sell
Menu items
A description of a menu item, pretty basic
"Main" menu items
These are all the "top level", "stand alone" menu items and in our case, can have condiments :D
Condiments
Condiments are a "special"
MenuItem, as they are associated with aMainMenuItemBurgers
This is just a demonstration of some of the things you could do,
Burgerisn't anything special, but as you will see, we can use this concept to do different thingsOrder
And finally, the "order", what have we ordered and what condiments do we want with it
This is a good demonstration of the power of the model. The
Orderhas agetTallymethod, which is used to calculate what is owed. Different implementations of the model might apply different calculations, like tax or discountsImplementations
Okay, since you're probably aware, we can't create an instance of a
interface, we need some "default" implementations to work with...Okay, try not to get too caught up in this, but have a look at the use of
abstracthere.AbstractMenuItemencapsulates a lot of the "common" functionality that allMenuItemimplementations are going to need, so we don't need to repeat ourselves, sweet.Some of these implementations are already making decisions or applying rules. For example, the
DefaultOrderwill clear thecondimentswhen ever theMainMenuItemis changed. It could also make sure that the condiment which is been applied is actually available fo this item.Also note, the
tallymethod is not a stored property, but is re-calculated every time you call it. This is design decision, it wouldn't be hard to make it a stored property instead, so each time you change theMenuMenuItem, add and/or remove condiments, the property was updated, but I'm feeling lazy. But you can see how these things can be changed, and it will effect ALL users of these models, sweet :DOkay, but how does this actually answer the question? Well, quite a bit actually.
So, the idea is, you start with a blank
Order. The user selects a "main item" (ie a burger), you set this to theOrderand then you update the UI in response. The UI asks theOrderto calculate thetallyand presents that to the user.More over, the same concept works for condiments as well. Each time a condiment is added or removed by the user, the
Orderis updated and you update the UI.Okay, but maybe, it's a little easier to understand with an example...
Okay, that's a lot to take in. Lets take a closer look at the
buildBurgerMenumethod. This gets called when ever the main menu is changed.Pay close attention to the
actionListenerused in this method, there's only one and it's shared by all the buttonsWhen ever the
actionListeneris triggered (via a user interaction for example), it makes a bunch of decisions, which, if all goes well, ends in theOrderbeen updated, thebuildCondimentsandorderDidChangemethods been called, which updates the available condiments and updates the UI's tally.This is all done in a "abstract" way. The
actionListenerdoesn't care about what type ofMainMenuItemthe user selected, that doesn't change its workflow, it only needs to apply the item to theOrder. In the same vain, theOrderdoesn't care, as it just needs thepriceinformation in order to calculate the tally.So you can add new menu items and/or change the prices and everything just keeps on working ().
Let's look at the
orderDidChangemethod...Not super complicated is it! All the work is been done by the, MODEL!
What I left out
For brevity, I left out one other concept, often used with models, the concept of the "observer pattern".
The observer pattern allows an interested party to be notified when some other object changes. It's pretty common concept and you've already used,
ActionListeneris an example of an observer pattern. It allows you to "observer" "actions events" when they are triggered by a given object.Sure, but how is that helpful?
Well, imagine now if, instead of having to manually call
orderDidChangeevery time you wanted to update the UI (or even forgetting to and spending a few hours debugging why), theMenuPanecould, instead, registered itself as an observer directly to theOrderand be notified when the order changed!! Super sweet!This further helps you de-couple your code and makes it super easy to update the UI in a verity of ways independently of the model or other code requirements.
Models