This is a tricky one to explain. What I'm in the process of making is a framework/library that can take a Java Object (ideally a bean) and turn it into a GUI (various adapter classes turn an abstract UI object into a platform-specific GUI) where players can view and edit the information. This might sound like a security hole but a project I'm working on needs lots of user options editing, and this is ideal for that. The way I've decided to go about this is fairly simple:
- Scan a given class's fields and iterate over
- If the field has an associated getter and/or setter, wrap that into a "Properties" object, otherwise leave the field as it is
- Create a "ClassStructure" from the properties which is essentially a JavaScript prototype but with Constructors and other things omitted.
- Use this structure to create a GUI with a GUIAdapter class However, it then has to use these properties to get their returned values from a given object.
I'm not entirely sure how to handle this though. I've given myself 2 options:
-
Edit the Properties interface to have a getValue() method, and require a object to be passed when creating the ClassStructure. This means ClassStructure is no longer a prototype, and put simply is a Map mapping getter methods to their returned values. This is a bit slower, as you'd have to re-create a ClassStructure for each object you want to make a Menu for. However, it reduces the amount of bloat and means I don't have to make any other classes to get the values.
-
Make the Properties getValue() method take an object to get values from, and create a sort of "ValuedClassStructure" class which holds all the methods and fields AND their corresponding values. I'd then have to make a ValuedClassStructure factory, which takes a ClassStructure and an object, scans all of the Properties, maps them to the values from the object. This SHOULD be faster as ClassStructures are cached, so to generate ValuedClassStructures for say 30 String Objects would be as simply as calling each of the getter methods. However, it makes the project vastly more bloated (speaking from experience, I previously took this approach, it became very "spaghetti"-like, and so I'm rewriting), with more interfaces, implementations, and factories.
This is fairly confusing to explain, and probably even more confusing to explain, so I'll try and do it in a pseudocode type example
This is option 1. ClassStructures are per-instance, not per-class, meaning they are slower to generate because we can't have much caching, but there are fewer classes and dependencies on one another.
interface ClassSearcher {
ClassStructure ofClass(Class clazz, Object holderObject);
}
interface ClassStructure {
Object getHolderObject();
Set<Property> getProperties();
}
interface Property<V> {
V getValue();
}
This is option 2. ClassStructures are per-class, ValuedStructures are per instance. To get a mapping of getters to values, we first create a prototype ClassStructure, and then create a ValuedStructure from that prototype.
interface ClassSearcher {
ClassStructure ofClass(Class clazz);
ValuedStructure getValues(ClassStructure structure, Object holder);
}
interface ClassStructure {
Set<Property> getProperties();
}
interface Property<V> {
V getValue(Object o);
}
interface ValuedStructure {
Object getHolderObject();
Set<ValuedProperty> getProperties();
}
interface ValuedProperty<V> {
V getValue();
}
Currrently I'm leaning towards option 2, simply because it's faster and with careful thought when writing it means it won't become too "spaghetti"-like. However, I'm interested to hear what everyone else has to say. There might be an option 3 that I've completely overlooked, and all it took was another perspective. If anyone wants to try and understand the bigger picture, everything I currently have is in https://github.com/knightzmc/jui The original project is jui-core, the rewrite is jui-core-new (will be renamed when finished).
TL;DR: converting Java beans to GUI. should make a JavaScript-like prototype and then map getter return values separately, or should all of the mapping be done in one class?
Thanks for the help.
Aucun commentaire:
Enregistrer un commentaire