Variable listener between 2 classes - java

I have a problem for a month ago :S .This is it:
I have 3 classes:
Class 1:
TabbedPane with a MouseListener, when someone click on a tab, the mouse listener change a variable called "update".
This class have a method like this:
public boolean getUpdateMenuState(){
//Creates the update variable
boolean update = false;
//If a update is necessary
if(needUpdate = true){ //Need update is defined at top of the class
//Reset the update variable
needUpdate = false;
//Set the getUpdate variable to true
update = true;
System.out.println("The menu needs to be updated");
}
//return the update
return update;
}
The second class, is the main:
This class needs to know if the variable needUpdate changes, I have this method:
private void updateMenu(){
//Create a variable update
boolean update = false;
//Set the variable update to the get state
update = myTabbedPane.getUpdateMenuState();
//If a update is requiered, re-add the menu
if(update){
menu.addMenu(); //Call the third class that have the method addMenu
}
}
My problem is that I need to know constantly if the variable needUpdate is changed, and I don't know how to implement my own listener to do it.
I can't call the third class directly in the first class because I want to centralize the control on the second class.
Please, if someone can help me I'll be grateful.

This is a classic example where an Observer pattern is the ideal solution. Refer to this Implementing Observer Pattern post for the details of how to implement the Pattern.
PS: just saw your reply to one of the answers;
Best in your situation is to use a Class instead of the boolean variable and you can extend that class.

I would think that this is a classic case for using the Observer Design Pattern. Class 2 would be the Observer for things happening on the Subject i.e. Class 1 and do what it needs to do when it gets notified i.e. call addMenu() on Class 3.

Related

Law of demeter - using only one dot, could I improve this logic?

I have the following method:
private boolean reserveSeat(int selectedRow, int selectedSeat) {
if (show.getRows().get(selectedRow).getSeats().get(selectedSeat).getReservationStatus()) {
return false;
} else {
show.getRows().get(selectedRow).getSeats().get(selectedSeat).reserve();
setRowNumber(selectedRow);
setSeatNumber(selectedSeat);
return true;
}
}
which resides in a Reservation class. This class has a Show Object (show), A show has Rows (another object), Rows have Seats (another object).
My question is could this method be improved? I have read about LoD and worried that my dot signals a bad design though I think it is logical. It is the Seat object that knows if it is reserved or not. However is going from Show to Seat talking to strangers? or is it ok because of the way each object contains the next object?
Apologies if my questing is not clear. What seems to happen with me (probably because I am self taught) is I design stuff that works then I read some OOP design principles and think crap, it works but it is not good design!
Any advice appreciated.
Yes, that chain of calls is way too long.
If show is in charge of the seats,
then it would be better if it's fully in charge.
Right now it's not fully in charge,
because seats can be reserved without the show's knowing.
This fragmentation of responsibilities is strange.
You can put show fully in charge by not exposing Seat to the Reservation,
by hiding the seat status manipulations behind helper methods:
private boolean reserveSeat(int selectedRow, int selectedSeat) {
if (show.isSeatReserved(selectedRow, selectedSeat)) {
return false;
} else {
show.reserveSeat(selectedRow, selectedSeat);
setRowNumber(selectedRow);
setSeatNumber(selectedSeat);
return true;
}
}
Or, if you don't want show to be in charge of the seats,
then it should not be aware of the seats at all,
so then you would access seats not through show,
but another class that's in charge of that.
You're using show as a data object, and putting all the logic for handling that data in the class that contains it. This makes Show a data class and the enclosing class a god class.
The logic for handling data inside of show should really be inside the Show class itself (data is smart).
You could make a method in the Show class for reserving a seat. And equally, you could make a method in the Row class for reserving a seat.
Then one just passes on the message to the next until you get to Seat.
What if you changed the implementation of Show to use a 2D array for instance? That would break the code in your reservation class.
By doing these long chained calls, and not letting classes handle their own data. You are making the user classes dependent on the implementation the used data structures.
If you wanted to change one, you would have to update all the user classes, instead of just the one class that contains the data structure.
So thanks for the suggestions, the feedback really helped with my learning. So what I went on to do was the following, based on the relationsip--> A Reservation (now called Booking) has a Show, A Show has a Row, A Row has a Seat(s).
In the Booking class I now have this: Thanks #janos
private boolean reserveSeat(int selectedRow, int selectedSeat) {
if (show.isSeatReserved(selectedRow, selectedSeat)) {
System.out.println("Sorry, that seat has already been booked");
return false;
} else {
show.reserveSeat(selectedRow, selectedSeat);
setRowNumber(selectedRow);
setSeatNumber(selectedSeat);
System.out.println("This seat has now been booked.");
return true;
}
}
In the Show class I have this:
public boolean isSeatReserved(int selectedRow, int selectedSeat) {
if (getRow(selectedRow).getSeatStatus(selectedSeat)) {
return true;
} else
return false;
}
and in the Row class I have
public boolean getSeatStatus(int selectedSeat) {
return getSeat(selectedSeat).getReservationStatus();
}
I thought it may be useful to other people just starting out (like me) to show this graphically using before and after diagrams taken from the jarchitect tool which shows what a mess my code was in! I used the same logic to tidy up some other classes that "knew too much".

Hiding Multiple Elements in JTable via ButtonClick

I am currently working on a tool which edits data dynamically in a JTable. I want to hide the targeted row whenever a button is clicked. Right now I am using RowFilter. Whenever the button isClicked, a new filter is created:
RowFilter<MyTableModel, Object> rowFilter = null;
try {
rowFilter = RowFilter.notFilter(RowFilter.regexFilter(((String)dataTable.getValueAt(dataTable.getSelectedRow(), 0)),0));
} catch (java.util.regex.PatternSyntaxException e) {
return;
}
sorter.setRowFilter(rowFilter);
This only works for one element each time the button is clicked. I want to stay them hidden, so you can continously hide elemtens in the table. It is important to mention that I do not want to delete the rows, just hide them.
I hope someone has an easy answer for this, looking for quite a while now.
This method sorter.setRowFilter(rowFilter); is replacing the filter every time you "add" a new filter. So, it's "forgetting" the old rules. What you have to do is edit the existing filter to include the new rules for filtering.
Check out the documentation for more details.
In any case, I extracted a part of the documentation which you should try to implement.
From RowFilter Javadoc:
Subclasses must override the include method to indicate whether the
entry should be shown in the view. The Entry argument can be used to
obtain the values in each of the columns in that entry. The following
example shows an include method that allows only entries containing
one or more values starting with the string "a":
RowFilter<Object,Object> startsWithAFilter = new RowFilter<Object,Object>() {
public boolean include(Entry<? extends Object, ? extends Object> entry) {
for (int i = entry.getValueCount() - 1; i >= 0; i--) {
if (entry.getStringValue(i).startsWith("a")) {
// The value starts with "a", include it
return true;
}
}
// None of the columns start with "a"; return false so that this
// entry is not shown
return false;
}
};
This means that the include() method is going to return true or false depending if an item should be shown.
Therefore, you should only set the RowFilter once, and reimplment the include() method to match all the rules you currently have set upon your view.

Only one instance of object from ListIterator moves

I am working on a game project. So far so good, but i just stuck on ome basic thing and i cant find a solution and make it work properly. I decided to come here and ask you ppl of suggestions.
PROBLEM:
First, I had 2 levels with one bot in each of them. Later i noticed, that only the bot in the first level updates its behavior. If i only load the next level, the bots update method is not called and i dotn know why.
I printed the ListIterator in to the console and the bot is there. But when i iterate trough the list in the main update method it seem it doesnt call the objects update method in it. I can still move with player and take diamonds from the map which both of them are also the part of the list so those methods are called. I can provide you with some smaller code blocks if you need to get some info on some specific things if i have them or not, just leave it in the comment. Here are some major blocks which in my opinion arent working proper.
If only the bot in the first level moves, i made another 4 bots to it. Only the first instance of Bot moves. All other items of the same class do nothing.
0.Declaration:
private ArrayList<AbstractObject> supp = new ArrayList<AbstractObject>();
private ListIterator<AbstractObject> objects=supp.listIterator();
1.Main update method:
public void update() {
resetList(); //sets the cursor at begining
if(menu.getChoice()==-1){
menu.update();
}
else if(menu.getChoice()==2)
System.exit(0);
else if(menu.getChoice()==0){
if(currentLevel>lvlm.getLevel() || currentLevel<lvlm.getLevel()){
clearList(); //remove all items in the list
init(lvlm.getLevelPath());
currentLevel=lvlm.getLevel();
}
while(objects.hasNext()){
objects.next().update(); //calls all updates from each object in the list
}
}
}
Update method in the Bot Class:
public void update() {
movingCount++;
switch(getFacing()){
case 2:
moved=true;
setFacing(2);
setVectorX(-0.5);
break;
case 3:
moved=true;
setFacing(3);
setVectorX(0.5);
break;
case 0:
case 1:
setVectorX(0);
moved=false;
}
if(movingCount>=200){
setFacing(randInt(0,3));
movingCount=0;
}
moveOnX(); //updates pos
moveOnY(); //updates pos
getAnimationL().runAnimation();
getAnimationR().runAnimation();
}
EDIT_1:
Ok so the bots only in the first line in the file move.
LEVEL 1
P-player
B-bots
D-diamonds
1-walls
1111111 B B
1P D 1
11111 1
1F 1 B
1111111
B B B
Any ideas why only first line bots move? Other line objects works properly.
Iterators only work once. You seem to be initialising the iterator once and then expecting it to work each time update is called.
Three options:
(Bad) reinitialise the iterator in update:
objects = supp.iterator();
(Better) don't use an iterator; use a for loop:
for (AbstractObject obj: supp) {
obj.update();
}
(Best) use a stream:
supp.stream().forEach(AbstractObject::update);
If the update could potentially remove an item then your best option is to remove them after you've processed the list. For example, create a boolean method in AbstractObject called shouldBeRemoved. Then you can use the following:
supp.removeIf(AbstractObject::shouldBeRemoved);
After you have used one of the three methods above to process the list.

Displaying live data to UI

I have a main class where the UI is located and that it instantiates another class, where the logic is located. I create the instance of the logic only when a button is clicked.
private void computeActionPerformed(java.awt.event.ActionEvent evt) {
//A STAR MISPLACED
EightPuzzle ep2 = new EightPuzzle(stringToInt(initial),"mis");
solution = ep2.getSolution();
aMisplacedSpace.setText(ep2.getNodesTraversed()+" nodes"); // I would like to display this during the search and not just after
setCurrentTilesAStarMisplaced(solution.size()-1);
}
The problem is that I have to display the number of nodes traversed during a particular instance into some JLabel in the UI. I guess my current structure does not allow me to do so. Is there a work around on this?

Setting the value of a variable from another class in Java

I was wondering if it is possible to reset the value of a variable from another class. For example I have this variable in a HillClimber (hc) class:
public int ballWeight = 200;
What I want to do is run a simulation of a game with the ball weighting at this value. When it is finished I want to set the value to 201 from another class and begin the simulation again, and after that increase to 202 and start another and so on. My problem is that every time I restart the simulation the ballWeight variable is reset to 200. I have tried using a setter method in the HillClimber class:
public int setBallWeight(int ballWeight) {
return this.ballWeight = ballWeight;
}
and called it from another class at the end of a simulation:
hc.setBallWeight(hc.ballWeight+1);
but this does not seem to work as the variables stored value is not changed. Does anyone know how I can do this so the stored value of ballWeight will be increased by 1 each time a simulation ends? Or is this even possible? Thanks.
Usually in a POJO you have what are called a getter and a setter method for every variable of the object. In your case:
public class HillClimber{
private int ballWeight;
public HillClimber(){
this.ballWeight = 200;
}
public void setBallWeight(int ballWeight){
this.ballWeight = ballWeight;
}
public int getBallWeight(){
return this.ballWeight;
}
}
In this way you can access the variable ballWeight via get and set method. You don't access it directly like in hc.ballWeight, which is possible but is a bad practice, and prevent this access type declaring your variable as private (meaning that only the class in which it is declared can directly access it).
To fullfill your request of adding one at every run of the game you can therefore call
hc.setBallWeight(++hc.getBallWeight()); //Equivalent to hc.setBallWeight(hc.getBallWeight() + 1);
I usually don't use this approach if the class isn't automatically generated (as in an Hibernate context), but instead declare another method in the HillClimber class
public void incrementBallWeight(int ballWeightToAdd){
this.ballWeight += ballweiGhtToAdd; //Equivalent to this.ballWeight = this.ballWeight + ballweiGhtToAdd;
}
or if I always need to add only one to my variable
public void incrementBallWeight(){
this.ballWeight++;
}
and then simply call incrementBallWeight after every game run.
NB: to have this working you will have to use always the same instance of HillClimber. In your main
public class Game{
private HillClimber hc = new HillClimber(); //Create the instance and sets ballWeight to 200
public static void main(String[] args){
playGame();
hc.incrementBallWeight(); //ballWeight == 201
playAnotherGame()
hc.incrementBallWeight(); //ballWeight == 202 -> Always the same instance of HillClimber (hc)
.
.
.
}
}
EDIT
I think your problem is greater than that. You are asking to save the state of a variable ( meaning that this value should be available also if you turn off and on your pc) without using a permanent storage. This is simply unachievable.
You should rethink your program (and I mean java program, not a "game run") to not stop after every game run. You can do this in different ways: via Swing GUI, via user input from stdin and so on. If you want some help on this topic, we need to know more of your code (maybe putting the whole of it is best).
OR you can use a file to store your value, which is not as difficult as you think. (Also).

Categories