Suppose I have a Player
class with an Inventory
:
public abstract class Player {
private final List<GameObject> gameObjects;
public Player(){
this.gameObjects = new ArrayList<GameObject>();
}
public add(GameObject item);
public drop()
}
I also have two items, Night Vision Goggles and a Tablet, with the following behaviors:
NVG:
- turn on/off
- utilize
- zoom
Tablet:
- turn on/off
- change system date
- schedule backup
- change username
For basic usage, I could have the following interface and implementation:
GameObject:
public interface GameObject {
boolean prepare();
boolean utilize();
boolean cleanup();
}
NightVisionGoggles:
public final class NightVisionGoggles implements GameObject {
// constructor left out
@override
public boolean prepare(){
System.out.println("Turning on Night Vision")
}
@override
public boolean utilize(){
System.out.println("Looking around in the dark")
}
@override
public boolean cleanup(){
System.out.println("Taking off Night Vision")
}
}
Tablet:
public final class DataPad implements GameObject {
// constructor left out
@override
public boolean prepare(){
System.out.println("Turning on Datapad")
}
@override
public boolean utilize(){
System.out.println("Browsing data")
}
@override
public boolean cleanup(){
System.out.println("Shutting down for the night")
}
}
The properties missing are the NVG's Zoom (0, 50, 100), and the tablets backup, system time and username. Both are properties but obviously of different types.
Because both are settings of each object, I could restructure my interface like this:
public interface GameObject {
boolean prepare();
boolean utilize();
boolean cleanup();
boolean tryChange(String name, String value);
boolean tryChange(String name, int value);
boolean tryChange(String name, DataTime value);
Map<String,String getSettings();
Map<String,int> getSettings();
Map<String,LocalDateTime> getSettings();
}
This would mean the objects would require at least 2 Maps<K,V>
. The NVG can return false for the tryChange(String name, DataTime value)
method
and return an empty collection in the Map<String,LocalDateTime> getSettings()
method. The tablet might use all 3, because a number of settings are either string
, int
or LocalDateTime
.
It doesn't feel right to me that the NVG would be aware of the LocalDateime
.
As the title says, without violating LSP and SRP how would you structure the interface and classes so that I can have the required behavior and store it in one collection?
All of this is assuming that a player inventory is only one collection, in real world games I don't know how it's modeled or stored, but I don't want to avoid the issue.