I have a class Car which has 2 properties: int price and boolean inStock. It also holds a List of abstract class State (empty class). There are 2 states which can be applied on the car and each is represented by its own class: class Upgrade extends State and class Shipping extends State.
A Car can hold any number of each of the 2 states. The states have the following rules:
Upgrade: adds1to the price for each state applied to the car after itself.Shipping: if there is at least 1Shippingstate in the list, theninStockis set tofalse.
For example, starting with price = 1 and inStock = true:
add Shipping s1 --> price: 1, inStock: false
add Upgrade g1 --> price: 1, inStock: false
add Shipping s2 --> price: 2, inStock: false
add Shipping s3 --> price: 3, inStock: false
remove Shipping s2 --> price: 2, inStock: false
remove Upgrade g1 --> price: 1, inStock: false
remove Shipping s1 --> price: 1, inStock: false
remove Shipping s3 --> price: 1, inStock: true
I was thinking about the observer pattern where each add and remove operations notify observers. I had something like this in mind, but it doesn't obey the rules I posed:
abstract class State implements Observer {
public abstract void update();
}
class Car extends Observable {
List<State> states = new ArrayList<>();
int price = 100;
boolean inStock = true;
void addState(State state) {
if (states.add(state)) {
addObserver(state);
setChanged();
notifyObservers();
}
}
void removeState(State state) {
if (states.remove(state)) {
deleteObserver(state);
setChanged();
notifyObservers();
}
}
}
class Upgrade extends State {
@Override
public void update(Observable o, Object arg) {
Car c = (Car) o;
int bonus = c.states.size() - c.states.indexOf(this) - 1;
c.price += bonus;
System.out.println(c.inStock + " " + c.price);
}
}
class Shipping extends State {
@Override
public void update(Observable o, Object arg) {
Car c = (Car) o;
c.inStock = false;
System.out.println(c.inStock + " " + c.price);
}
}
Obviously, this doesn't work. When a Shipping is removed, something has to check if there is another state setting inStock to false, so a removal of Shipping can't just inStock = true. Upgrade increases price at each call. I then added constants for the default values and attempted a recalculation based on those.
I am by no means trying to impose any pattern, I'm just trying to find a solution for the above requirements. Note that in practice Car contains many properties and there are many states that can be applied in this manner. I thought about a few ways to do this:
- Since each observer receives
Car, it can look at all the other observers currently registered and make a change based on that. I don't know if it's smart to entangle observers like this. - When an observer is added or removed in
Car, there will be a recalculation. However, this recalculation will have to be done on all observers regardless of the one which was just added/removed. - Have an external "manager" class which will call the add and remove methods and do the recalculation.
What is a good design pattern to implement the described behavior and how would it work?