Reputation: 313
I have a need to have a unique name for a subset of objects in java. Basically I have a display object and multiple instances of it. Each instance of a display needs to have a unique name for auditing purposes. This is so when you look at the audit you will know what display was audited. What I am looking for is how to do this as a best practice possibly using a design pattern. Here are some of my current ideas
IDEA 1 Use toString() every object already has a toString so overriding this should provide an easy way to name the objects. The down side to this is all objects have a toString so it is hard to enforce that the Display objects have theirs filled out while everything else does not need it.
IDEA 2 Use an interface. I could make an interface called IDisplayName with a function called getName(). My Display object could implement this interface so my concrete classed will need to set it. This is what I currently have implemented.
IDEA 3 Same as IDEA 2 but have getName() return an ENUM instead of a String. This way I could maybe enforce uniqueness in a single file and the ENUMs would have a displayString attribute. The problem with this is there are a lot of said Display objects >100 so this can get really big really fast.
IDEA 4 Just log the class name. This does not work well since the audit is not read by programmers so I would prefer to make the audit more friendly.
Thanks in advance for any help.
Upvotes: 3
Views: 1644
Reputation: 27946
My view is that you should use an interface. While it is, of course, possible to reuse toString
or the class name for this purpose it is clearly overloading their use in a way that will not be clear to future readers. For example, if a future refactor splits classes the audit trail will change in an undefined manner. Similarly toString
implementation could change for a number of reasons.
Rather than calling your interface IDisplayName
I would suggest calling it Auditable
or similar to make it's purpose obvious. Ideally your audit methods would then take an Auditable
.
interface Auditable {
public String getAuditName();
}
Upvotes: 1
Reputation: 30879
I wouldn't use the toString, because it could have other purposes (like debugging) or printing the object state. If returning the class name is not clear to non programmers it's probably not clear to programmers as well. I mean, if you use principles of clean code your class name should be clear to everyone. Then you must of course remove the package by displaying only a simplified class name: String simplifiedClassName = qualifiedClassName.substring(qualifiedClassName.lastIndexOf(".") + 1).
If you want to be more flexible, your IDisplayName.getName
could be defined like this:
default String getName() {
String qualifiedName = getClass().toString();
return qualifiedName.substring(qualifiedName.lastIndexOf(".") + 1);
}
It is an interface default method, meaning programmers may override it only in the classes they feel they must.
Another possibility, if you need internationalization/localization:
your getName
could read the name from a properties file, where the property
key is the simplified class name. Property files can be edited by non programmers, and a property file with 100 entries is not a big one. It's also easy to guarantee uniqueness of values in a properties file.
Edit For Java 7: Apart from the IDisplayName
interface, create a class called DisplayNameUtil
, where getName
is a static method:
public static String getName(Object obj) {
String qualifiedName = obj.getClass().toString();
return qualifiedName.substring(qualifiedName.lastIndexOf(".") + 1);
}
Then, in your most of your display classes (or a common superclass) you can add this:
@Override
public String getName() {
return DisplayNameUtil.getName(this);
}
Programmers will still be able to return specific names for selected classes,
and the interface getName
may still access a properties file if you want.
Having an Util class that provides default behavior to interface methods was a Java 7 pattern. By the way, removing companion Util classes is a recommended refactoring when moving from Java 7 to 8. In other words, if your code ever gets translated to Java 8 it's very easy to refactor this to use a default method in the interface and remove the Util class.
Upvotes: 1
Reputation: 7800
If the class just needs to be unique, then I would just have each instance of your display object associated with some ID and this is how I would do it: In your Display class, you should have a static constant and every instance of display should be assigned an ID. That ID would be whatever the value of the constant in Display at the time. Then once you assign the id value, you increase the value of the constant. Then you give your Display class a getId() method that would allow you to call it on all subclasses and obtain a unique identifier for each instance.
public class Display(){
private static int idCounter = 0;
private final int id;
public Display(){
id = idCounter++;
}
public int getId(){
return id;
}
}
Now each instance of Display (including subclasses) will now have this unique ID that you can call to identify it as such.
Upvotes: 0