Java hashCode for similar classes - java

I have two similar classes, each with a single field of the same type.
class Fruit {
private final String name;
}
class Vegetable {
private final String name;
}
I'd like to implement hashCode() for each. My problem is that in my case, collisions between names are somewhat more possible than with "apple" and "carrot," and they both might be in the same Map/Set. I'm wondering what's the most clear way of implementing hashCode to handle this.
So far, I've considered Objects.hash(this.getClass(), name), Objects.hash(<some int unique to this class>, name). I like the first just because it's a bit more self-documenting and robust than the second, but it's not a pattern I've seen in the wild. I also considered <some prime int unique to this class> * Objects.hashCode(name), but that felt fragile, especially if a new field gets added.

Assuming the 2 classes extend a common parent class, I solved this by adding a second field that would tell the instances of two different classes apart. This may be regarded as just another way of using the class name suggested by David Ehrmann in his question. But in my case using an additional field looks more appropriate than using a class name. So here's my abstract parent class:
public abstract class NationalDish {
public String dishName;
public String country;
#Override
public int hashCode() {
return Objects.hash(country, dishName);
}
#Override
public boolean equals(Object obj) {
if (!(obj instanceof NationalDish)) {
return false;
}
NationalDish other = (NationalDish) obj;
return Objects.equals(dishName, other.dishName)
&& Objects.equals(country, other.country);
}
}
Note how having the fields in the parent class allows to define equals() and hash code() in that same class and keep child classes to the minimum:
public class EnglishDish extends NationalDish {
public EnglishDish(String dishName) {
this.dishName = dishName;
this.country = "England";
}
}
public class AmericanDish extends NationalDish {
public AmericanDish(String dishName) {
this.dishName = dishName;
this.country = "USA";
}
}
Now, with country names (or plant types like in the question) in place we can have same name instances which will look different to Java:
public static void main(String[] args) {
NationalDish englishChips = new EnglishDish("Chips");
NationalDish americanChips = new AmericanDish("Chips");
System.out.println(englishChips.equals(americanChips)); // false
}

Related

Make several classes have the same attributes without inheritance

I'm facing a problem in Java.
I need to have several classes with the same attributes ( for example a Position and a boolean isWalkable ).
But I don't want these classes to inherit from a class Element because that would prevent me from using inheritance later.
I thought of an interface (so that the interface has the attributes), but apparently you can't have an interface inherit from a class.
There must be a way because otherwise I would have to copy/paste my attributes and there methods.
Thanks in advance for anyone who has an idea on how to overcome this problem.
For this, I would consider composition over inheritance.
public class Main {
public static void main(String[] args) {
AgentWrapper agentWrapper = new AgentWrapper(new Agent1(), false, 1);
System.out.println("isWalkable: " + agentWrapper.isWalkable());
System.out.println("position: " + agentWrapper.getPosition());
agentWrapper.getAgent().doSomething();
}
}
interface Agent {
void doSomething();
}
class Agent1 implements Agent {
public void doSomething() {
System.out.println("Agent1");
}
}
class Agent2 implements Agent {
public void doSomething() {
System.out.println("Agent1");
}
}
class AgentWrapper {
private final Agent agent; //Wrapped instance.
private final boolean isWalkable;
private final int position;
public AgentWrapper(Agent agent, boolean isWalkable, int position) {
this.agent = agent;
this.isWalkable = isWalkable;
this.position = position;
}
public Agent getAgent() {
return agent;
}
public boolean isWalkable() {
return isWalkable;
}
I suspect you might need an interface anyway, if you want to treat your objects generically - e.g. loop over all of them and draw each one. E.g. assuming your elements include "cats" and "houses":
interface Element{
public point getPosition();
public boolean isWalkable();
}
class Cat implements Element{
private Point position;
private String catBreed; // example of cat-specific data
public point getPosition() {return position;}
public boolean isWalkable() {return true;} // cats can walk
...
}
class House implements Element{
private Point position;
private String streetAddress; // example of house-specific data
public point getPosition() {return position;}
public boolean isWalkable() {return false;} // houses cannot walk
..
}
// Finally, using that common interface:
Element[] allGameObjects= {new Cat(...), new Cat(...), new House(...) };
for(Element e:allGameObjects)
draw(e, e.getPosition());
That was good enough for several system I wrote... but as other replies correctly mentioned, you might refactor to use composition - however it might not be a 100% clear-cut. I mean, I can understand if you feel Cat or House should be managed independently from their position... but what about isWalkable?
// Position is easy to separate:
class Cat { String catBreed; ... }
class House{ String streetAddress; ... }
class ElementWrapper implements Element{
Point position;
Object theObject; // could hold Cat or House
public Point getPosition() {return position;}
// however, isWalkable is a bit tricky... see remark below
}
But 'isWalkable' is tricky because in classic polymorphism you'd expect House/Cat to tell you whether they can walk (meaning they should implement an interface anyway). If you absolutely don't want (or cant) have it, you may compromise on polymorphism and do something in the lines of instanceof (if theObject is instanceof Cat then it can walk, if it's instanceof House it cannot walk, etc).
You can extend an abstract base class(containing nothing) or You can use the Decorator pattern as somebody suggested in the comments, for more information related to Decorator pattern you can read this link.

Is there someway to restrict the access to a member of an object only to the object that owns it by composition?

I really feel like there must be a way around this.
Imagine I have a large number of objects as components of an owner class. I want to offer easy access to the clients of this owner class to its members, so I make all those objects public. Each of those objects also have all their members public. But one member of the components should not be accessible to the clients of their owner, only by their owner itself:
public class ComponentObject
{
public int int_field;
public float float_field;
public Object object_field;
public Object public_method1()
{
//something;
}
public Object public_method2()
{
//something;
}
public Object restricted_to_owner_only()
{
//something;
}
}
//all clients of Owner should be able to access all the members of its components, except
//restricted_to_owner_only, which only Owner should be able to access
public class Owner
{
public ComponentObject component1;
public ComponentObject component2;
public ComponentObject component3;
//... lots of others
public ComponentObject component300;
}
Is there a way to achieve this? Note that any class from any package can own a ComponentObject, so using package level visibility at restricted_to_owner_only doesn't seem to be an option. ComponentObject is like a utility class, reusable in other applications.
Maybe there's an annotation that enforces that at compile time in some nice lib out there?
EDIT: I forgot to mention that ComponentObject is a parameterized type in real life, and each field in Owner is parameterized differently. I tried to abstract off the details so we could focus on the design problem itself, but I abstracted too much. I will post bellow something more similar to the real problem:
public class ComponentObject<T>
{
public int int_field;
public float float_field;
public T object_field;
//any method could return T or take T as an argument.
public T public_method1()
{
//something;
}
public Object public_method2()
{
//something;
}
public Object restricted_to_owner_only()
{
//something;
}
}
//all clients of Owner should be able to access all the members of its components, except
//restricted_to_owner_only, which only Owner should be able to access
public class Owner
{
public ComponentObject<String> component1;
public ComponentObject<File> component2;
public ComponentObject<Consumer<Boolean>> component3;
//... lots of others
public ComponentObject<Integer> component300;
}
EDIT 2 (Possibly a solution): Guys, inspired by Romeo and Juliet's love, I wrote this solution, can you spot any faults with it? Or would it work as I intended?
//add this class
public class OwnershipToken
{
private static int id_gen = 0;
public final int id = id_gen++;
#Override
public boolean equals(Object obj)
{
return (obj instanceof OwnershipToken) && ((OwnershipToken)obj).id == id;
}
#Override
public int hashCode()
{
return id;
}
}
//Then change this in ComponentObject<T>:
public class ComponentObject<T>
{
//add this field:
private final OwnershipToken ownershipToken;
//add this constructor
public ComponentObject(OwnershipToken onwershipToken)
{
this.ownershipToken = ownershipToken;
}
//change restricted_to_owner_only signature:
public Object restricted_to_owner_only(OwnershipToken ownershipToken)
{
//add this condition
if(this.ownershipToken.equals(ownershipToken)
//something;
}
}
//finally, Owner gains a field:
public class Owner
{
private final OwnershipToken ownershipToken = new OwnershipToken();
//... etc, remainder of the class
}
would this work as intended?
I understand what you want and that is impossible i think.
But, there is still one way to do it!
Make an id in the owner class:
private int id = new Random().nextInt(10000);
In ComponentObject:
private id;
public ComponentObject(int id){
this.id = id;
}
public Object restricted(int id){
if(this.id != id)
return null;
else
return object;
}
In owner:
private ComponentObject<String> string;
public Owner() {
string = new ComponentObject<>(id);
string.restricted(id);
//if the id is right it will return the restricted object, if not i will
//return null
}

Should base class attribute controlled by Derived class

I am currently working on designing some system where I'm confused if it will be right to control base class attributes with derived class.
For example:
Class Building {
String name;
String[] facilities;
}
Class OfficeBuilding extends Building{
}
Class ResidentialBuilding extends Building {
}
//Type of Building control attribute like facilities here which is empty by default. Should it be part of Derived classes or it should remain part of Base class and derived classes should just override its values ?
Things to keep in mind:
1). All classes are data classes here.
2). Base class facilities attribute is always empty and controlled by child class.
Thanks.
There is more than one solution. Not knowing your use case I would say name and facilities can be fully managed by parent class, not even directly accessible from child classes (only via constructor / some methods). I would also store facilities as list:
Class Building {
private String name;
private List<String> facilities;
public Building(String name, String... facilities) { // facilities won't be null this way
this.name = name;
this.facilities = new ArrayList<String>(Arrays.asList(facilities));
}
public Building(String name) {
this(name, new String[0]);
}
// Only if this makes sense
public Building() {
this("");
}
public String[] getFacilities() {
return facilities.toArray(new String[facilities.size()]);
}
// if needed you can...
public void addFacility(String facility) { ... }
public void removeFacility(String facility) { ... }
}
Class OfficeBuilding extends Building {
public OfficeBuilding() {
super("Office", "facility1", "facility2");
//...
}
}

Avoid Type Casting During Data Processing

I can't seem to figure out the best approach to tackle the following problem. Let's say there is an abstract base class with several concrete subclasses:
public abstract class AbstractType { /* common properties */ }
public class TypeA { /* properties of type A */ }
public class TypeB { /* properties of type A */ }`
These are domain classes (JPA entities). The properties of the types are (amongst other things) used to validate user data. I'm under the assumption that adding logic to the domain model itself is considered bad practice. Therefore, I want to avoid adding a validate method to the concrete subclasses. Like so:
UserInput userInput = ...;
AbstractType data = ...;
data.validate(userInput);
I don't see an option without having to cast the domain model,
if I want to move the logic to a logic layer. With the limited knowledge I have, I can only come up with following two similar "solutions", using some kind of handler interface.
Keep some explicit reference to the handler in the type
public interface TypeHandler {
public validate(AbstractType data, UserInput userInput);
}
/* TypeAHandler & TypeBHandler implementations */
public enum Type {
TYPE_A(new TypeAHandler()),
TYPE_B(new TypeBHandler());
private TypeHandler handler;
public Handler(TypeHandler handler){
this.handler = handler;
}
public TypeHandler getHandler(){ return handler; }
}
public class TypeA {
private Type type = TYPE_A;
/* ... */
}
The handler would than be called in the following manner:
UserInput userInput = ...;
AbstractType data = ...;
data.getType.getHandler().validate(data, userInput);
The reference to the handler could also be added immediately (without the enum in between) as property to the AbstractType class, but that would mean there is a reference to a class inside the logic layer from the domain model (which kind of defeats the purpose of moving the logic to a logic layer?)
The problem here too is that the validate method inside the TypeXHandler needs to cast the data argument to its subclass first before it can start validating.
Or I could implement some method which has a large if-then structure to get the right subclass, cast it and call the appropriate handler which implements an interface similar to the following.
public interface TypeHandler<T extends AbstractType> {
public validate(T data, UserInput userInput);
}
So in both cases there is casting. In the first case there is no huge if-then structure, but the logic and domain are not separated. In the second case there is a very inflexible if-then structure.
To conclude, here is my question. Should I really avoid implementing the logic directly inside the domain? If so, is there any way to avoid the casting, the if-else structure and/or adding additional properties to the domain model (like the enum in the first "solution").
At the end of the day, you're branching based on the subtype (concrete classes) since the logic to validate user input is based on those specific details contained in the subclasses.
Generics don't really help you much here since generics are based primarily on applying logic that is uniform across different types, operating on universal logic applied to a common interface that all applicable types share. Here your logic and interface varies for each subtype.
So your main choices are an inextensible solution where you're modifying central source code (like a big bunch of ifs/elses, a map, etc) and manually branching based on subtype, or using abstraction/dynamic polymorphism as an extensible solution which doesn't require modifying any central source code and automatically branches based on subtype.
Reflection might also be a possible route if you can afford it (it's a bit expensive at runtime) and provided it can fit to give you that universal logic you can implement centrally.
If you don't want to add this validate method to AbstractType and all of its subtypes, then you can always add another level of abstraction on top which does contain a validate method like ValidatorB which implements the IValidator interface and stores an object of TypeB as a member and applies the logic used to validate user input using TypeB's properties.
I studied design patterns last week and I would like to propose my solution (it works but I'm not sure that is the smartest way to resolve your problem).
The idea of my solution is to use a factory: you give a model (in your case a JPA entity) to the factory and it gives you the correct validator for that model.
At the beginning of the program, you have to tell to the factory which is the validator class for each model class of your program through a register method.
Let's start with the implementation...
AbstractModel.java
public abstract class AbstractModel
{
private final int commonProperty;
protected AbstractModel(int commonProperty)
{
this.commonProperty = commonProperty;
}
public int getCommonProperty() { return commonProperty; };
}
In the AbstractModel we put all the common properties of the models.
ModelA.java
public class ModelA extends AbstractModel
{
private final int specificProperty1;
private final int specificProperty2;
public ModelA(int commonProperty, int specificProperty1, int specificProperty2)
{
super(commonProperty);
this.specificProperty1 = specificProperty1;
this.specificProperty2 = specificProperty2;
}
public int getSpecificProperty1() { return specificProperty1; }
public int getSpecificProperty2() { return specificProperty2; }
}
ModelA has got two specific properties.
ModelB.java
public class ModelB extends AbstractModel
{
private final int specificProperty1;
private final int specificProperty2;
public ModelB(int commonProperty, int specificProperty1, int specificProperty2)
{
super(commonProperty);
this.specificProperty1 = specificProperty1;
this.specificProperty2 = specificProperty2;
}
public int getSpecificProperty1() { return specificProperty1; }
public int getSpecificProperty2() { return specificProperty2; }
}
ModelB has got two specific properties too.
Let's say that an instance a of ModelA is valid iff
a.commonProperties == a.specificProperty1 + a.specificProperty2
and an instance b of ModelB is valid iff
b.commonProperties == b.specificProperty1 * b.specificProperty2
Validator.java
public interface Validator
{
public boolean validate();
}
A really simple interface for the validators.
AbstractValidator.java
public abstract class AbstractValidator implements Validator
{
private final AbstractModel toBeValidated;
protected AbstractValidator(AbstractModel toBeValidated)
{
this.toBeValidated = toBeValidated;
}
protected AbstractModel getModel()
{
return toBeValidated;
}
}
This is the superclass of the concrete validators that wraps the model to be validated.
ValidatorA.java
public class ValidatorA extends AbstractValidator
{
protected ValidatorA(AbstractModel toBeValidated)
{
super(toBeValidated);
}
public boolean validate()
{
ModelA modelA = (ModelA) getModel();
return modelA.getCommonProperty() == modelA.getSpecificProperty1() + modelA.getSpecificProperty2();
}
}
The validator for the instances of ModelA.
ValidatorB
public class ValidatorB extends AbstractValidator
{
protected ValidatorB(AbstractModel toBeValidated)
{
super(toBeValidated);
}
public boolean validate()
{
ModelB modelB = (ModelB) getModel();
return modelB.getCommonProperty() == modelB.getSpecificProperty1() * modelB.getSpecificProperty2();
}
}
And this is the validator for the instances of ModelB.
And finally it comes the factory!
ValidatorFactory.java
public class ValidatorsFactory
{
private static ValidatorsFactory instance;
private final HashMap<Class<? extends AbstractModel>, Class<? extends Validator>> registeredValidators;
private ValidatorsFactory()
{
registeredValidators =
new HashMap<Class<? extends AbstractModel>, Class<? extends Validator>>();
}
public static ValidatorsFactory getInstance()
{
if (instance == null)
instance = new ValidatorsFactory();
return instance;
}
public void registerValidator(
Class<? extends AbstractModel> model,
Class<? extends Validator> modelValidator)
{
registeredValidators.put(model, modelValidator);
}
public Validator createValidator(AbstractModel model)
{
Class<? extends Validator> validatorClass = registeredValidators.get(model.getClass());
Constructor<? extends Validator> validatorConstructor = null;
Validator validator = null;
try
{
validatorConstructor = validatorClass.getDeclaredConstructor(new Class<?>[] { AbstractModel.class });
validator = (Validator) validatorConstructor.newInstance(new Object[] { model });
}
catch (NoSuchMethodException | SecurityException | InstantiationException | IllegalAccessException | IllegalArgumentException | InvocationTargetException e)
{
System.err.println(e.getMessage());
// handle exception
}
return validator;
}
}
The factory is a singleton with two significant method:
registerValidator to add a new pair (modelClass, validatorClass) in the HashMap.
createValidator to obtain the correct validator for the specified model.
This is how to use this pattern:
public class Main
{
public static void main(String args[])
{
ValidatorsFactory factory = ValidatorsFactory.getInstance();
factory.registerValidator(ModelA.class, ValidatorA.class);
factory.registerValidator(ModelB.class, ValidatorB.class);
ModelA modelA = new ModelA(10, 4, 6);
if (factory.createValidator(modelA).validate())
System.out.println("modelA is valid");
else
System.out.println("modelA is not valid");
ModelB modelB = new ModelB(10, 8, 2);
if (factory.createValidator(modelB).validate())
System.out.println("modelB is valid");
else
System.out.println("modelB is not valid");
}
}
output:
modelA is valid [because 10 = 4 + 6]
modelB is not valid [because 10 != 8 * 2]
Note that the model is completely separeted from the controller and it uses only one cast from AbstractModel to a concrete model.
Hope it helps!

Determine which subclass to choose by accessing static variables from the Class object

I am trying to implement an interface in Java to use different types of databases for one application.
My though was to create an abstract class with the common interface and two static variables which are then overwritten by the subclasses. I then wanted to add a Class[] List with the classes of all available subclasses to the abstract class as well as a couple of functions that allow the determination of the correct class to be used.
The goal is to first get a list of all available database types and let the user choose one. Afterwards another function should translate the name (which could be localized) to the IDENTIFIER which is specified in the subclass. Finally a third function allows the instantiation of an object by giving such an IDENTIFIER.
My abstract class would look something like this:
public abstract class DataBase {
public static final IDENTIFIER = "";
public static final NAME = "";
private static final Class[] dbTypes = new Class[]{PostgreSQL.class, MySQL.class};
public static String[] getNameList() {
String[] names = new String[dbTypes.length];
for(int i = 0; i < dbTypes.length; i++){
names[i] = dbTypes[i].NAME; //Cannot access the static variable this way.
}
return names;
}
public static String getIdentifierForName(String name) {
for(int i = 0; i < dbTypes.length; i++){
if(name.equals(dbTypes[i].NAME){
return dbTypes[i].IDENTIFIER;
}
}
return "";
}
public static DataBase getInstanceOf(String identifier) {
for(int i = 0; i < dbTypes.length; i++){
if(identifier.equals(dbTypes[i].IDENTIFIER) {
return dbTypes[i].newInstance();
}
}
return null;
}
}
The Child classes would look something like this:
public class MySQL extends DataBase {
public static final IDENTIFIER = "ab.cde.MySQL";
public static final NAME = "MySQL";
...
}
public class PostgreSQL extends DataBase{
public static final IDENTIFIER = "ab.cde.PostgreSQL";
public static final NAME = "PostgreSQL";
...
}
My problem now is, that I cannot access the static variables from the Class object. Obviously the dbTypes list does not contain any typed classes. I tried changing the type of the Array to Class<? extends DataBase>, but I get an error Cannot create a generic array of Class<? extends DataBase> I also tried checking the classes with isAssignableFrom() and then casting the class, but I was still not able to access the static variables.
For now I have two solutions which are working:
Hardcode all existing subclasses into each function if(PostgreSQL.NAME.equals(name)){...}etc.
However, if I add new subclasses, I only want to have to add them at one point in my implementation.
Instead of using a Class[] array, I can use an array of DataBase[] with instances of each class. However, I would think this is bad practice to instantiate each available DataBase subclass, even though I only need one in the end.
Since I have never done such a thing before I might also be approaching the problem completely wrong. Maybe I am missing the correct way in which something like this is usually done?
Thank you for your help.
There are no "abstract properties" in Java. You have to create two astract methods in the DataBase class, like this:
public abstract class DataBase {
// No "abstract propeties"
public abstract String getDBName();
public abstract String getDBIdentifier();
// etc etc...
}
and then, in each subclass:
public class MySQL extends DataBase {
public static final IDENTIFIER = "ab.cde.MySQL";
public static final NAME = "MySQL";
#Override
public String getDBName() {
return NAME;
}
#Override
public String getDBIdentifier() {
return IDENTIFIER;
}
// etc etc...
}
When using the classes, you can just cast to DataBase (not MySQL or PostgreSQL) and call the two abstract methods.
Therefore, in order to solve your "pick a database class" problem, I would create a configuration file that contains the names of the databases and the corresponding class, and instantiate it with reflection (newInstance()) as needed.
As an alternative, you can use reflection to access the static variables like Nikita's answers suggested, or you can just use the name of the class as the identifier of the database it supports, like this (not tested):
public abstract class DataBase {
private static final Class[] dbTypes = new Class[]{PostgreSQL.class, MySQL.class};
public static Class getDBClass(String type) {
for (Class c : dbTypes) {
if (c.getSimpleName().toLowerCase().equals(type.toLowerCase())) {
return c;
}
}
return null;
}
public static Set<String> getSupportedDB() { // <-- you populate a dropdown menu with this
Set<String> supported = new HashSet<String>();
for (Class c : dbTypes) {
supported.add(c.getSimpleName());
}
return supported;
}
// etc etc...
}
However, I don't like this solution and I would not use it.
You can use reflection to get values for each class:
public static String[] getNameList(){
String[] names = new String[dbTypes.length];
for(int i=0; i<dbTypes.length; i++){
Field f = dbTypes[i].getField("NAME");
names[i] = f.get(null);
}
return names;
}
But it might be slow.
Also I'd suggest to create separate enum DBRegistry that will contain names, identifiers and classes:
public enum DBRegistry {
MYSQL("ab.cde.MySQL", "MySQL", MySQL.class),
POSTGRESQL("ab.cde.PostgreSQL", "PostgreSQL", PostgreSQL.class);
private String name;
private String identifier;
private Class<?> dbClass;
private DBRegistry(String identifier, String name, Class<?> dbClass) {
this.identifier = identifier;
this.name = name;
this.dbClass = dbClass;
}
// Getters...
}
You can iterate on all items in registry using DBRegistry.values
Not tested, but I would suggest something like this. You could register databases by calling DataBase.registerDataBase(new DataBase(...))); which may be invoked from the main file.
public class DataBase {
private final static List<DataBase> INSTANCES = new ArrayList<DataBase>();
private final String identifier;
private final String name;
private final Class<?> dbType;
public DataBase(String identifier, String name, Class<?> dbType) {
this.identifier=identifier.toString();
this.name=name.toString();
this.dbType=dbType;
}
String getIdentifier() {return identifier;}
String getName() {return identifier;}
Class<?> getDbType() {return dbtype;}
public synchronized static void registerDatabase(DataBase database) {
database.getClass();
INSTANCES.add(database);
//may check if already registered and either fail or replace it
}
public synchronized static List<DataBase> getNameList() {
return new ArrayList<DataBase>(INSTANCES);
}
public synchronized static List<String> getNameList() {
List<String> names = new ArrayList<String>(INSTANCES.size());
for (Database db:INSTANCES) names.add(db.getName());
return names;
}
public synchronized static String getIdentifierForName(String name) {
for(DataBase db:INSTANCES){
if(name.equals(db.getName())) return db;
}
return null;
}
public synchronized static DataBase getInstanceOf(String identifier) {
for(DataBase db:INSTANCES){
if(identifier.equals(db.getIdentifier())) return db;
}
return null;
}
}
}
I would advise to keep it simple, never more than necessary to utilize in the actual application. It is easier to extend things than to re-factor code to accomodate for additional complexity. Most of the stuff you mention are merely artefacts of your problem solving, not the actual requirements of your application per se. And it so happens, that a modern object-oriented language has everything you need, and you can implement a good design without reflection and without resorting to static properties and string identifiers.
Remember to rely on the compiler rather than runtime for whatever you know in advance - anything that is known not to change from one application run to another, does not need reflection, because it does not involve runtime variables! I would go for interfaces, classes implementing them, and more importantly the Factory pattern to abstract using these classes:
interface Database
{
void query(String sqlString);
}
class MySQLDatabase implements Database
{
public void query(String sqlString)
{
}
}
class PostgreSQLDatabase implements Database
{
public void query(String sqlString)
{
}
}
class DatabaseFactory
{
Database connectDatabase()
{
/// F.e. return new MySQLDatabase();
}
}
The whole "database abstraction layer" has been done to death already anyway, giving birth to DBA, ODBC and other software stacks that solve your problem. You should let yourself be inspired by these, unless you are sure your particular way of solving this yields advantages that can be proven. If you want to go about this in a professional way, of course. If you want to educate yourself, by all means, use reflection, strings in place of more specific objects, and tight-coupling instead of aggressive modularity.

Categories