I am trying to understand the Memento Pattern. For that purpose i am trying to implement the undo function. The problem is that when ever i save the old state of the originator in the queue and run a different function the save state changes to the current state. I really need help to understand what i am doing wrong. How can i make the vector to be immutable.
This is the memento class.
package memento;
public class Memento
{
private final boolean[] vectorState;
public Memento(boolean[] vector) {vectorState = vector;}
boolean[] getMemento() { return vectorState;}
}
The Originator just need to shift a vector of boolean to the left.
(TRUE,FALSE,FALSE) shift left returns: (FALSE,FALSE,TRUE). This is the implementation.
package memento;
public class ShilftLeftOriginator
{
private boolean[] vector;
public ShilftLeftOriginator(boolean[] vector) {this.vector = vector;}
public void execute()
{
final boolean firstValue = this.vector[0];
for (int i = 1; i < this.vector.length; i++) {
this.vector[i - 1] = this.vector[i];
}
this.vector[vector.length - 1] = firstValue;
}
public Memento saveToMemento() {return new Memento(vector);}
}
And the caretaker:
package memento;
import java.util.Arrays;
import java.util.Deque;
import java.util.LinkedList;
public final class BooleanVector {
private boolean[] vector;
private Deque<Memento> mementoList = new LinkedList<>();
public BooleanVector(boolean[] inputValues) {
this.vector = inputValues;
}
#Override
public boolean equals(Object obj)
{
if (obj == null) return false;
if (!(obj instanceof BooleanVector)) return false;
BooleanVector otherVector = (BooleanVector) obj;
return Arrays.equals(this.vector, otherVector.vector);
}
public void shiftLeft()
{
ShilftLeftOriginator shiftLeft = new ShilftLeftOriginator(vector);
mementoList.add(shiftLeft.saveToMemento());
shiftLeft.execute(); // This is my Problem. After execute ist call the value(vector) in mementoList changes
}
public void undo(){ this.vector = mementoList.pop().getMemento();}
}
And now the test class and the error that i am receiving.
package memento;
public class Main {
public static void main(String[] args) {
boolean[] inputValues = { false, true, false };
BooleanVector vector = new BooleanVector(inputValues);
vector.shiftLeft();
boolean[] expectedValues = new boolean[] { true, false, false };
BooleanVector expectedVector = new BooleanVector(expectedValues);
if (!vector.equals(expectedVector)) {
throw new IllegalStateException(vector.toString());
} else {
System.out.println("shiftleft working");
}
vector.undo();
expectedValues = new boolean[] { false, true, false };
expectedVector = new BooleanVector(expectedValues);
if (!vector.equals(expectedVector)) {
throw new IllegalStateException(vector.toString());
} else {
System.out.println("undo working");
}
}
}
The console output:
shiftleft working
Exception in thread "main" java.lang.IllegalStateException: [true, false, false]
at memento.Main.main(Main.java:26)
The problem is that you're always manipulating the same array. So if you shift left, you also shift left the array you stored in the Memento object, because it's all the same array.
To solve it, make a copy of the array in the constructor of the Memento object:
public Memento(boolean[] vector) {
vectorState = Arrays.copyOf(vector, vector.length);
}
Aside from that, you seem to have your classes mixed up. BooleanVector and ShilftLeftOriginator are the originator, while Main is the caretaker.
I can give you a little bit more expandable solution:
class Originator: abstract implementatino of the value T holder
public abstract class Originator<T> {
private T value;
private final CareTaker<T> careTaker;
protected Originator(T value, CareTaker<T> careTaker) {
this.value = value;
this.careTaker = careTaker;
}
public final T getValue() {
return value;
}
protected final void setValue(T value) {
careTaker.add(this.value);
this.value = value;
}
public final void undo() {
if (!careTaker.isEmpty())
value = careTaker.remove();
}
}
class BooleanVector: concrete implementation that holds boolean[]
public final class BooleanVector extends Originator<boolean[]> {
public BooleanVector(boolean[] obj) {
super(obj, new CareTaker<>());
}
public void leftShift() {
if (getValue() == null || getValue().length == 0)
return;
boolean[] arr = new boolean[getValue().length];
boolean tmp = arr[0];
System.arraycopy(getValue(), 1, arr, 0, getValue().length - 1);
arr[arr.length - 1] = tmp;
setValue(arr);
}
}
class CareTaker: implementation of values change history - memento
public final class CareTaker<T> {
private final Deque<Item<T>> stack = new LinkedList<>();
public void add(T value) {
stack.push(new Item<>(value));
}
public T remove() {
return stack.pop().data;
}
public boolean isEmpty() {
return stack.isEmpty();
}
private static final class Item<T> {
private final T data;
public Item(T data) {
this.data = data;
}
}
}
Demo:
public static void main(String[] args) {
BooleanVector originator = new BooleanVector(new boolean[] { false, true, false });
System.out.println(Arrays.toString(originator.getValue()));
System.out.println("---");
originator.leftShift();
System.out.println(Arrays.toString(originator.getValue()));
originator.undo();
System.out.println(Arrays.toString(originator.getValue()));
}
Output:
[false, true, false]
---
[true, false, false]
[false, true, false]
Related
I am trying to make a class (and a few subclasses and interfaces) to represent a Polynomial. First I have a monomial class which has fields for a coefficient and degree of a Monomial.
public class Monomial {
int coef;
int degree;
public Monomial(int coef) throws IllegalArgumentException {
super();
this.degree = 1;
this.coef = coef;
}
public Monomial(int degree, int coef) throws IllegalArgumentException {
if (this.degree < 0) {
throw new IllegalArgumentException("non positive degree");
}
this.coef = coef;
this.degree = degree;
}
public int getDegree() {
return this.degree;
}
public int getCoef() {
return this.coef;
}
public boolean sameMonomial(Monomial that) {
return this.coef == that.getCoef()
&& this.degree == that.getDegree();
}
}
Next, I have two classes, which implement an interface called ILoMonomial. The ILo stands for (Interface List-of) and it used to represent a list of Monomials.
Therefore, the class MtLoMonomial is an empty list and the base case of the list, having no fields. The ConsLoMonomial class has two fields, a Monomial as the (first) item in the list, and An ILoMonomial as the (rest of the list).
public interface ILoMonomial {
boolean findAnyDupes();
boolean findAnyDupesHelper(int degree);
boolean findSameHelper(Monomial that);
boolean findSame(ILoMonomial that);
}
public class MtLoMonomial implements ILoMonomial {
MtLoMonomial(){}
#Override
public boolean findAnyDupes() {
return true;
}
#Override
public boolean findAnyDupesHelper(int degree) {
return true;
}
#Override
public boolean findSameHelper(Monomial that) {
return false;
}
#Override
public boolean findSame(ILoMonomial that) {
return false;
}
}
public class ConsLoMonomial implements ILoMonomial {
Monomial first;
ILoMonomial rest;
ConsLoMonomial(Monomial first, ILoMonomial rest) {
this.first = first;
this.rest = rest;
}
#Override
public boolean findAnyDupes() {
return this.rest.findAnyDupesHelper(this.first.getDegree()) &&
this.rest.findAnyDupes();
}
#Override
public boolean findAnyDupesHelper(int degree) {
return degree == this.first.degree;
}
public boolean findSameHelper(Monomial that) {
return that.sameMonomial(this.first);
}
#Override
public boolean findSame(ILoMonomial that) {
if (that.findSameHelper(this.first)) {
return true;
} else {
return that.findSame(this.rest);
}
}
}
Finally, I have my Polynomial class, which is where I am running into trouble on how to go about implementing the samePolynomial class. In this class, the only field I have is the ILoMonomial.
I have no idea how to go about this. I have a few helper methods in the classes which implement ILoMonomial (findSame, and findSameHelper)
(but as of now only findSameHelper works and possibly only for the first item in the list).
Here is some example code
import static org.junit.Assert.*;
import org.junit.Before;
import org.junit.Test;
public class ExamplesPolynomial {
Monomial oneRaisedToFourth = new Monomial(1, 4);
Monomial twoRaisedToOne = new Monomial(2, 1);
Monomial twoSquared = new Monomial(2 , 2);
Monomial threeXSquared = new Monomial(3, 2);
Monomial five = new Monomial(5, 1);
Monomial coefOf2 = new Monomial(2);
ILoMonomial threeXSquaredPlusFive = new ConsLoMonomial(
threeXSquared, new ConsLoMonomial(
five, new MtLoMonomial()));
ILoMonomial ListOfMonomial1 = new ConsLoMonomial(oneRaisedToFourth,
new MtLoMonomial());
ILoMonomial duplicateDegree = new ConsLoMonomial(twoRaisedToOne,
new ConsLoMonomial(coefOf2, new MtLoMonomial()));
ILoMonomial threeXSquaredPlusFive_Reversed = new ConsLoMonomial(five,
new ConsLoMonomial(threeXSquared, new MtLoMonomial()));
Polynomial error = new Polynomial(duplicateDegree);
Polynomial fine = new Polynomial(threeXSquaredPlusFive);
// passes
#Test(expected = IllegalArgumentException.class)
public void testPolynomial(){
Polynomial error = new Polynomial(duplicateDegree);
}
// passes
#Test
public void testPolynomialTrue() {
Polynomial noError = new Polynomial(new ConsLoMonomial(threeXSquared,
new ConsLoMonomial(twoRaisedToOne, new MtLoMonomial())));
}
// passes
#Test
public void testSameMonomial() {
assertTrue(coefOf2.sameMonomial(coefOf2));
assertFalse(coefOf2.sameMonomial(threeXSquared));
}
// passes
#Test
public void testFindSameHelper() {
assertTrue(ListOfMonomial1.findSameHelper(oneRaisedToFourth));
assertFalse(ListOfMonomial1.findSameHelper(threeXSquared));
}
// fails : assertion error
#Test
public void testFindSame() {
assertTrue(threeXSquaredPlusFive.findSameHelper(five));
}
// fails : assertion error
#Test
public void testSamePolynomial() {
Polynomial reverse = new Polynomial(threeXSquaredPlusFive_Reversed);
Polynomial normal = new Polynomial(threeXSquaredPlusFive);
assertTrue(reverse.samePolynomial(normal));
}
}
In all the searching I did, I could not find an example of this sort. My bad :(
I have an Optional object containing an array. I now need to traverse the array and locate a particular element inside it.
Codes and sample classes as follows:
public class Component {
private String name;
public Component(String ipName) {
this.name = ipName;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
public class Container {
private Component[] componentArray;
public Container(Component[] ipComponentArray) {
this.componentArray = ipComponentArray;
}
public Component[] getComponentArray() {
return componentArray;
}
public void setComponentArray(Component[] componentArray) {
this.componentArray = componentArray;
}
}
public class TestClass {
public static void main(String[] args) {
Container newContainer = getNewContainer();
System.out.println(checkIfComponentIsPresent("Two", newContainer)); //prints true
System.out.println(checkIfComponentIsPresent("Five", newContainer)); //prints false
}
private static Container getNewContainer() {
return new Container(new Component[] {new Component("One"), new Component("Two"), new Component("Three")});
}
private static boolean checkIfComponentIsPresent(String ipName, Container newContainer) {
boolean isPresent = false;
Optional<Component[]> componentArrayOptional = Optional.ofNullable(newContainer).map(Container::getComponentArray);
if(componentArrayOptional.isPresent()) {
Component[] componentArray = componentArrayOptional.get();
if(componentArray != null && componentArray.length > 0) {
for(Component component : componentArray) {
if(ipName.equals(component.getName())) {
isPresent = true;
break;
}
}
}
}
return isPresent;
}
}
Can someone please advise me how can I improve the method checkIfComponentIsPresent? I want to know how can we traverse an array inside an Optional object, without converting it into a list or stream.
I can do it using streams as follows:
private static boolean checkIfComponentIsPresentUsingStreams(String ipName, Container newContainer) {
boolean isPresent = false;
Optional<Component[]> componentArrayOptional = Optional.ofNullable(newContainer).map(Container::getComponentArray);
if(componentArrayOptional.isPresent()) {
Stream<Component> componentArrayStream = Arrays.stream(componentArrayOptional.get());
isPresent = componentArrayStream.filter(component -> ipName.equals(component.getName())).findFirst().isPresent();
}
return isPresent;
}
But I cannot use streams, actually my classes are huge, and the array itself can contain numerous elements. Using streams, will degrade the performance.
Thanks!
You can operate with actual object value inside map method:
boolean isPresent = Optional.ofNullable(newContainer)
.map(Container::getComponentArray)
.map(arr -> {
for (Component component : arr) {
if (Objects.equals(component.getName(), ipName)) {
return true;
}
}
return false;
})
.orElse(false);
Actually I am sure what makes you think Stream would slow down your app significantly. And therefore there is another solution using streams:
boolean isPresent = Optional.ofNullable(newContainer)
.map(Container::getComponentArray)
.map(arr -> Stream.of(arr).anyMatch(component -> Objects.equals(ipName, component.getName())))
.orElse(false);
I have a class with the boolean field and I want field of only one object to be true at the same time.
I tried to set field of all objects with static method but i could not reach non-static field from static method.(i wasn't aware of logic behind static)
public class ToggleBox
{
private boolean selected;
public ToogleBox()
{
selected=false;
}
public setOnlyTrue()
{
setAllFalse();
selected=true;
}
private static setAllFalse()
{
this.selected=false;
}
}
Is there any trick to do this or should i iterate over all objects of class to change all the fields?
One trick I could think of is having a static member that holds the reference of the one instance that has a true property:
public class MyClass {
private static MyClass trueObject = null;
public void setProperty(boolean value) {
if (value) {
trueObject = this;
} else {
trueObject = null;
}
}
public boolean getProperty() {
return trueObject == this;
}
}
It depends on you requirement when you want to create an instance with trueand a true has already been created
A. set ALL the others to false and the new one to true
public class ToggleBox {
private static List<ToggleBox> listAll = new ArrayList<>();
private boolean selected;
public ToggleBox(boolean bool) {
if (bool) // if require true
for (ToggleBox mo : listAll)
mo.setSelected(false); // set all other to false
listAll.add(this);
this.selected = bool;
}
public void setSelected(boolean bool) { this.selected = bool; }
#Override
public String toString() { return selected + ""; }
public static void main(String argv[]) {
ToggleBox m1 = new ToggleBox(true);
ToggleBox m2 = new ToggleBox(false);
System.out.println(Arrays.toString(listAll.toArray())); // [true, false]
ToggleBox m3 = new ToggleBox(true);
System.out.println(Arrays.toString(listAll.toArray())); // [false, false,true]
}
}
B. refuse to set the new one to true
public class ToggleBox {
private static boolean alreadyTrue = false;
private static List<ToggleBox> listAll = new ArrayList<>();
private boolean selected;
public ToggleBox(boolean bool) {
if (bool) { // if require true
if (alreadyTrue) // if there is already one
bool = false; // it will be false
else // else
alreadyTrue = true; // it's st to true, and remember it
}
this.selected = bool;
}
#Override
public String toString() { return selected + ""; }
public static void main(String argv[]) {
ToggleBox m1 = new ToggleBox(true);
ToggleBox m2 = new ToggleBox(false);
System.out.println(Arrays.toString(listAll.toArray())); // [true, false]
ToggleBox m3 = new ToggleBox(true);
System.out.println(Arrays.toString(listAll.toArray())); // [true, false, false]
}
}
I'm writing a game-like program and it has a class that has to act as an item. Normally I would just keep it as an item but every one has to wait 10 game-days in order to start doing what it's meant to. Is there a way to update the days in all the classes at once? I've tried to use a static method but you can't use instance variables in those so it didn't work. I've thought about possibly making a code that expands every time a new instance is made but I can't find anything i can understand about it. Is there any way to add to a method, make this an item, anything? This is what I have at the moment:
public class Tree
{
private boolean fullGrown;
private int day;
private int APDay; //apples per day
private static int totalApples;
public Tree()
{
fullGrown = false;
day = 0;
APDay = (int) (Math.random()*2) + 4;
}
public void updateDay()
{
day = day + 1;
if (day == 10) fullGrown = true;
if (fullGrown == true) totalApples = totalApples + APDay;
}
public void skipGrowth()
{
fullGrown = true;
}
}
Although this works, you have to update the day for every instance separately. I need a way to update all the instances at the same time. This will also be used by a code and not the actual interface, just in case that's helpful.
Observer and factory pattern looks like a good candidate here.
I hope the code below explain rest to you
public interface DayEventListener {
public void onDay10(DayEvent DayEvent);
}
public class DayEvent {
//... pojo
}
public class AwesomeGame {
private List<DayEventListener> dayEventListenerList = new ArrayList<>();
public void addDayListener(DayEventListener del) {
dayEventListener.add(del);
}
public void fireDay10Event(DayEvent de) {
for(DayEventListener del : dayEventListenerList) {
del.onDay10(de);
}
}
public class Item implements DayEventListener {
//All constructors should be private
public static Item buildItem() {
Item Item = new Item();
awesomeGame.addDayEventListener(Item);
return item;
}
}
so I did some research and while I was working on another project I discovered that i could use a vector to keep track of all my instances, so here is that class:
import java.util.Vector;
public class catcher
{
private static Vector allInstances = new Vector();
private int catchLeft;
private String name;
public catcher(String name)
{
catchLeft = Integer.parseInt(name.substring(name.indexOf("#") + 1, name.length()));
catchLeft--;
this.name = name;
if (catchLeft != 0) allInstances.add(this);
}
public static synchronized Vector getAllInstances()
{
return (Vector) (allInstances.clone());
}
public boolean check(String name, boolean change)
{
boolean foo;
if (this.name.equals(name))
{
if (change == true) catchLeft--;
foo = true;
}
else foo = false;
if (catchLeft <= 0) this.finalize();
return foo;
}
public void finalize()
{
allInstances.removeElement(this);
}
public static void clear()
{
allInstances.clear();
}
}
now that I have a record of all the instances, I used this method in another class to assess all the instances:
import java.util.Iterator;
import java.util.Vector;
public class recipe
{
private boolean checkForList(String name, boolean add)
{
Iterator list = catcher.getAllInstances().iterator();
boolean running = true;
boolean booleanReturn = true;
while (running == true)
{
if (list.hasNext())
{
catcher Foo = (catcher) (list.next());
if (Foo.check(name, false) == true)
{
Foo.check(name, true);
running = false;
booleanReturn = true;
}
}
else
{
if (add == true) new catcher(name);
running = false;
booleanReturn = false;
}
}
return booleanReturn;
}
}
I'm sure that this can be modified to update the classes instead of just accessing them.
I'm having difficulty passing arrays between methods, I've managed to set them all to false from boolean, and returned the array to the main. However from there I don't know how to pass it to another method, and then later display the boolean true array as "yes" or the boolean false array as "no". My code looks as follows:
import javax.swing.*;
class methodarrays
{
public static void main (String[]param)
{
arrays();
seen();
display();
}
public static boolean[] arrays()
{
boolean [] birds = new boolean [5];
for (int i=0;i<birds.length;i++)
{
birds[i]=false;
}
return birds;
}
public static boolean seen()
{
String quit = "100";
String ans = "";
while(!ans.eqauls(quit))
{
ans=JOptionPane.showInputDialog(null,"Which bird are you reporting? \n 1) Blue Tit 2) Blackbird 3)Robin 4)Wren 5)Greenfinch");
if (ans.equals("1"))
{
birds[0] = true;
return birds[0];
}
else if (ans.equals("2"))
{ birds[1] = true;
return birds[1];
}
else if (ans.equals("3"))
{
birds[2] = true;
return birds[2];
}
else if (ans.equals("3"))
{
birds[2] = true;
return birds[2];
}
else if (ans.equals("4"))
{
birds[3] = true;
return birds[3];
}
else if (ans.equals("5"))
{
birds[4] = true;
return birds[4];
}
}
}
public static void display()
{
JOptionPane.showMessageDialog(null,"Your Garden Watch results are:");
}
}
To give you are starting hand... you can set the result of your arrays method to a local variable in the main method and pass as a argument to the seen. Then you can do the same for the display method.
public static void main (String[]param)
{
boolean[] birds = arrays();
seen(birds);
display(birds);
}
public static boolean[] arrays()
{
...
}
public static boolean seen(boolean[] birds)
{
...
There are plenty of tutorials around the web for this kind thing. Here being one example.
You need to pass it as a parameter or declare a global array.
Passing by parameter:
class methodarrays {
public static void main (String[]param)
{
boolean [] myArray =arrays();
seen(myArray);
display(myArray);
}
public static boolean seen(boolean [] myArrayParam)
{
for (int i=0;i<myArrayParam.length;i++)
{...}
}
public static boolean display(boolean [] myArrayParam)
{
for (int i=0;i<myArrayParam.length;i++)
{...}
}
}
As global array:
class methodarrays {
boolean [] myArray
public static void main (String[]param)
{
myArray = arrays();
seen();
display();
}
public static boolean seen()
{
for (int i=0;i<myArray.length;i++)
{...}
}
public static boolean display()
{
for (int i=0;i<myArray.length;i++)
{...}
}
}
Declare
boolean [] birds = new boolean [5];
as accessible object for all methods within your class.
import javax.swing.*;
class methodarrays
{
private boolean [] birds = new boolean [5]
...
public static boolean[] arrays()
{
for (int i=0;i<birds.length;i++)
{birds[i]=false;
}
return birds;
}
...
}
Here is the implementation mimicing your own:
import javax.swing.JOptionPane;
public class Example {
private static boolean [] birds = new boolean [5];
public static void main (String[]param){
arrays();
seen();
display();
}
public static boolean[] arrays()
{
// Completely unnecessary since values are set to false by default;
for (int i=0;i<birds.length;i++)
{birds[i]=false;
}
return birds;
}
public static void seen(){
String quit = "100";
String ans = "";
while(!ans.equals(quit))
{
ans=JOptionPane.showInputDialog(null,"Which bird are you reporting? \n 1) Blue Tit 2) Blackbird 3)Robin 4)Wren 5)Greenfinch");
if (ans.equals("1"))
{ birds[0] = true;
}
else if (ans.equals("2"))
{ birds[1] = true;
}
else if (ans.equals("3"))
{ birds[2] = true;
}
else if (ans.equals("3"))
{ birds[2] = true;
}
else if (ans.equals("4"))
{ birds[3] = true;
}
else if (ans.equals("5"))
{ birds[4] = true;
}
}
}
public static void display(){
System.out.println("Your results are: ");
System.out.println("Blue Tit: " + birds[0]);
System.out.println("Blackbird: " + birds[1]);
//and so on..
}
}