Ich möchte gerne ganz genau die Instanzen mehrere Klassen zählen, dazu habe ich folgendes mir überlegt:
Eine Counter Klasse, verwaltet in einer Map Wrapperklasse:
Man bemerke, dass ich ConcurrentHashMap genommen habe, wenn möglich soll das ganze Thread sicher sein.
Nun die Liste sollte Möglichst auch nicht doppelt vorkommen, und das Interface hat sich Singleton für sie angeboten:
Das ganze funktioniert auch gut, aber ich habe 1 Problem:
Vererbung, wenn ich folgende 2 Klassen habe:
und
ist der Output wenn ich ein CountableAA erstelle:
statt dem eigentlichen gewünschten:
Ich weiß schon, dass irgendwie das getName sich nur um die Aufrufende Instanz kümmert, nicht um die Klasse wo es drinnen steht, aber kann man das entsprechend besser machen?
Diese ganze Möglichkeit im Interface auch direkt den String zu übergeben, gehen schon ein bisschen in diese Richtung, aber ich habe gehofft, dass ich drumherum komme die Namen hart coden zu müssen. Und vorallem was mache ich bei abstrakten Klassen? Auch kann ich es im Interface erzwingen, dass eine untere Klasse wie zum Beispiel CountableAA ihre eigenen Methoden verwenden muss?
Java:
public class InstanceCounter {
private int instances;
private final String nameOfCountedObject;
public InstanceCounter(String objectName){
instances=0;
nameOfCountedObject=objectName;
}
public String getNameOfCountedObject(){
return nameOfCountedObject;
}
public void increaseInstanceCounter(){
instances++;
}
public void restetCounter(){
instances=0;
}
public boolean noInstance(){
return instances==0;
}
public void reduceInstanceCounter(){
if(instances>0){
instances--;
}
}
public int getNumberOfInstances(){
return instances;
}
/* (non-Javadoc)
* @see java.lang.Object#toString()
*/
@Override
public String toString() {
StringBuilder builder = new StringBuilder();
builder.append("InstanceCounter [countedObject=");
if (nameOfCountedObject != null) {
builder.append("nameOfCountedObject=");
builder.append(nameOfCountedObject);
}
builder.append(", instances=");
builder.append(instances);
builder.append("]");
return builder.toString();
}
}
Java:
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
public class InstanceCounterSingletonList {
private Map<String, InstanceCounter> map;
public InstanceCounterSingletonList() {
map = new ConcurrentHashMap<String, InstanceCounter>();
}
public InstanceCounter getInstanceCounterForClass(String classname, boolean increase){
InstanceCounter returnCounter;
if(map.containsKey(classname)){
returnCounter=map.get(classname);
}else{
returnCounter=new InstanceCounter(classname);
map.put(classname, returnCounter);
}
if(increase){
returnCounter.increaseInstanceCounter();
}
return returnCounter;
}
public InstanceCounter getInstanceCounterForClass(String classname){
return getInstanceCounterForClass(classname, false);
}
public void increaseInstanceCounterForClass(String classname){
getInstanceCounterForClass(classname).increaseInstanceCounter();
}
public void restetCounterForClass(String classname){
getInstanceCounterForClass(classname).restetCounter();
}
public boolean noInstanceOfClass(String classname){
return getInstanceCounterForClass(classname).noInstance();
}
public void reduceInstanceCounterForClass(String classname){
getInstanceCounterForClass(classname).reduceInstanceCounter();
}
public int getNumberOfInstancesForClass(String classname){
return getInstanceCounterForClass(classname).getNumberOfInstances();
}
}
Nun die Liste sollte Möglichst auch nicht doppelt vorkommen, und das Interface hat sich Singleton für sie angeboten:
Java:
/**
* Acts as a Singleton for the InstanceCounterSingletonList itself, countable things should easily
* tell their names.
*/
public interface Countable {
InstanceCounterSingletonList instanceCounterList=new InstanceCounterSingletonList();
public String getClassName();
public static InstanceCounter createInstanceCounter(String callingName){
return instanceCounterList.getInstanceCounterForClass(callingName, true);
}
public static InstanceCounter getInstanceCounter(String callingName){
return instanceCounterList.getInstanceCounterForClass(callingName);
}
public static void increaseInstanceCounter(String callingName){
instanceCounterList.increaseInstanceCounterForClass(callingName);
}
public static void restetCounter(String callingName){
instanceCounterList.restetCounterForClass(callingName);
}
public static boolean noInstance(String callingName){
return instanceCounterList.noInstanceOfClass(callingName);
}
public static void reduceInstanceCounter(String callingName){
instanceCounterList.reduceInstanceCounterForClass(callingName);
}
public static int getNumberOfInstances(String callingName){
return instanceCounterList.getNumberOfInstancesForClass(callingName);
}
public static InstanceCounter createInstanceCounter(Countable calling){
return instanceCounterList.getInstanceCounterForClass(calling.getClassName(), true);
}
public static InstanceCounter getInstanceCounter(Countable calling){
return instanceCounterList.getInstanceCounterForClass(calling.getClassName());
}
public static void increaseInstanceCounter(Countable calling){
instanceCounterList.increaseInstanceCounterForClass(calling.getClassName());
}
public static void restetCounter(Countable calling){
instanceCounterList.restetCounterForClass(calling.getClassName());
}
public static boolean noInstance(Countable calling){
return instanceCounterList.noInstanceOfClass(calling.getClassName());
}
public static void reduceInstanceCounter(Countable calling){
instanceCounterList.reduceInstanceCounterForClass(calling.getClassName());
}
public static int getNumberOfInstances(Countable calling){
return instanceCounterList.getNumberOfInstancesForClass(calling.getClassName());
}
public static InstanceCounterSingletonList getCounterList(){
return instanceCounterList;
}
}
Vererbung, wenn ich folgende 2 Klassen habe:
Java:
public class CountableA implements Countable
{
public String getClassName(){
return this.getClass().getName();
}
/**
* Constructor for objects of class CountableA
*/
public CountableA() {
System.out.println(Countable.createInstanceCounter(this));
}
}
Java:
public class CountableAA extends CountableA{
/**
* Constructor for objects of class CountableAA
*/
public CountableAA()
{
super();
System.out.println(Countable.createInstanceCounter(this.getClass().getName()));
}
}
Code:
InstanceCounter [countedObject=nameOfCountedObject=CountableAA, instances=1]
InstanceCounter [countedObject=nameOfCountedObject=CountableAA, instances=2]
Code:
InstanceCounter [countedObject=nameOfCountedObject=CountableA, instances=1]
InstanceCounter [countedObject=nameOfCountedObject=CountableAA, instances=1]
Diese ganze Möglichkeit im Interface auch direkt den String zu übergeben, gehen schon ein bisschen in diese Richtung, aber ich habe gehofft, dass ich drumherum komme die Namen hart coden zu müssen. Und vorallem was mache ich bei abstrakten Klassen? Auch kann ich es im Interface erzwingen, dass eine untere Klasse wie zum Beispiel CountableAA ihre eigenen Methoden verwenden muss?
Zuletzt bearbeitet: