# Programierstil: static - Zugriff vs. Staticzugriff



## huckleberry (4. Jul 2012)

Hallo,

mir ist kein besserer Titel eingefallen.

Ich habe eine Singleton-Klasse:

```
public class MySingleton {
	
	private long myvalue;
	//private static long myvalue; 

	private MySingleton(){
		myValue = -1;
	}

	public static MySingleton getInstance(){
		if (mySingleton == null) mySingleton = new MySingleton();
		return mySingleton;
	}
	
	//..
}
```

Dabei muss ich eine Methode für andere Klassen zur Verfügung stellen. Hätte ich 2 Möglichkeiten. 
a)

```
public long calculatedValue(long l){
		return myValue+l;
	}
```
und dann rufe ich aus von woanders folgendes auf

```
long test = MySingleton.getInstance().calculatedValue(3);
```

ODER b)

```
public static long calculatedValue(long l){
		return myValue+l;
	}
```
und dann rufe ich aus von woanders direkt folgendes auf

```
long test = MySingleton.calculatedValue(3);
```

Gibts es Vor- und Nachteile? Performance etc.?

VG Huck


----------



## HelgeW (4. Jul 2012)

Einen Singleton solltest Du einsetzen, wenn es innerhalb der Klasse gilt bestimmte Zustände zu merken oder Daten zu puffern, die ueber den einfachen Aufruf hinaus gehen ( z.B. Cache, Message etc. )

Bei Deinem Beispiel ist es ja nur eine einfache Berechnung und daher würde ich es als static methode implementieren.


----------



## maki (4. Jul 2012)

Ein einziges "GoF" Singleton macht zB. dann Sinn, wenn man keine Lust/Möglichekit hat ein DI Framework zu nutzen, mehere Singletons machen eingentlich keinen Sinn mehr, weil DI hier die bessere Wahl ist.

"GoF" Singletons werden meist falsch eingesetzt als globale Variablen, danach hört sich hier die Beschreibung an.

Wenn "GoF" Singletons Zustände halten, muss man auch synchronization achten, wenn sie keine Zustände halten, braucht man kein Singleton sondern eine statische Utilitymethode, oder besser eine stinknormales nicht-statisches Objekt 



> Einen Singleton solltest Du einsetzen, wenn es innerhalb der Klasse gilt bestimmte Zustände zu merken oder Daten zu puffern, die ueber den einfachen Aufruf hinaus gehen ( z.B. Cache, Message etc. )


Hi HelgeW,

dafür "braucht" man kein "GoF" Singleton, geht besser ohne


----------



## bygones (4. Jul 2012)

warum brauchst du ueberhaupt eine instanz der klasse ? nach dem bsp hast du einfach eine reine static class ala Math.


----------



## huckleberry (4. Jul 2012)

maki hat gesagt.:


> Ein einziges "GoF" Singleton macht zB....


Was ist "GoF" ?




bygones hat gesagt.:


> warum brauchst du ueberhaupt eine instanz der klasse ? nach dem bsp hast du einfach eine reine static class ala Math.



Das war nur ein Beispiel. Mein Singleton ist selbstverständlich komplexer und beinhält ein Kommunikationsprotokoll, welches sich bestimmte Timeout Werte merkt.


----------



## Gast2 (4. Jul 2012)

huckleberry hat gesagt.:


> Was ist "GoF" ?


Das ist die Gang of Four:
http://de.wikipedia.org/wiki/Entwurfsmuster_(Buch)
In dem wird auch über das Singleton Pattern diskutiert.



> Das war nur ein Beispiel. Mein Singleton ist selbstverständlich komplexer und beinhält ein Kommunikationsprotokoll, welches sich bestimmte Timeout Werte merkt.


Kannst du die Klasse mal zeigen? Muss das wirklich nen Singleton sein?


----------



## tfa (4. Jul 2012)

huckleberry hat gesagt.:


> Was ist "GoF" ?



Die "Gang of Four" haben das Buch Design Patterns geschrieben. Hier wird auch das Signleton-Muster vorgestellt. Da es so schön einfach und gut zu verstehen ist, wird es gerade von Anfängern gerne missbraucht. 

Später hat Erich Gamma (einer der GoF) zugegeben, dass das Singleton eventuell doch eher ein Antipattern und kein Pattern ist:



> When discussing which patterns to drop, we found that we still love them all. (Not really—I'm in favor of dropping Singleton. Its use is almost always a design smell.)



Quelle




> Das war nur ein Beispiel. Mein Singleton ist selbstverständlich komplexer und beinhält ein Kommunikationsprotokoll, welches sich bestimmte Timeout Werte merkt.


Komplexität ist kein Grund, ein Singleton einzuführen. Versuch's einfach mal ohne.


----------



## FArt (4. Jul 2012)

Tipps:
1. Vermeide Singletons dieser Art (wurde schon erwähnt)
2. Wenn ein Singleton nicht lazy initialisiert werden muss, dann initialisieren ihn sofort in einem static Field oder synchronisiere die Instanziierung (wurde so ähnlich schon  erwähnt)
3. Mach dir keine Gedanken um Performance bei einfachen Zugriffen
4. Nutze eine DI Framework und verwende eine Instanz anstatt ein "Singleton" (wurde schon erwähnt)
5. und allgemein: KISS


----------



## ARadauer (4. Jul 2012)

Wiederspricht sich 4 und 5 nicht gewalltig wenn man Anfänger ist?
Wiederspricht sich 4 in sich selbst nicht da eine normale "Spring Bean" ja auch ein Singleton ist?


----------



## maki (4. Jul 2012)

huckleberry hat gesagt.:


> Was ist "GoF" ?


EikeB hat es zwar schon erklärt. wollte aber nochmal was dazu sagen...

Die "Gang of Four" haben in ihrem Buch das Singleton mit static Feld bzw. Zugriff gezeigt (getInstance bzw. INSTANCE), inklusive LazyLoading (was eigentlich fast nie Sinn macht, dafür aber den Code komplexer und fehlerträchtiger) und privatem Konstruktor. Leider wird dieses beispiel meist ohne Nachzudenken abgetippt... inkl. aller negativen Eigenschaften (static Zugriffe sind schwer zu testen, hartcodierte Abhängigkeit, fehlende/falsche Synchronization für das LazyLoading, "Seperation of Concerns" ist verletzt, weil Zugriff und Erzeugung im Gof Singleton beide geregelt werden) 

Bei einem DI Framework sagt man eifnach "das ist ein Singleton, also immer dieselbe Instanz verwenden", kein static Zugriff bzw. static Feld, kein privater Konstrutor, keine der Nachteile wie zB. schlechte Testbarkeit, einfach nur eine normale Klasse von dem nur eine Instanz erzeugt wird vom DI Framework: sauberer, testbar, einfacher -> besser



ARadauer hat gesagt.:


> Wiederspricht sich 4 und 5 nicht gewalltig wenn man Anfänger ist?
> Wiederspricht sich 4 in sich selbst nicht da eine normale "Spring Bean" ja auch ein Singleton ist?


Hi ARadauer,

so schwer ist DI auch nicht, geht auch ohne Framework, bei Konstruktor bzw. Setter Injection ohne Framework fällt einem zB. schnell auf falls etwas von überall und jedem verwendet wird -> Vielleicht doch etwas die Sichtbarkeit einschränken abnstatt eine globale Varibale zu verwenden? 
Ansonsten gibt es große Unterschiede zwischen einem Singleton und einem "Gof Singleton"


----------



## ARadauer (4. Jul 2012)

Ncihts gegen DI ich arbeite gerne mit Spring. Trotzdem muss man sich bewusst sein, dass man mit Singletons arbeitet. Überhaupt im Web Bereich!


----------



## maki (4. Jul 2012)

@ARadauer
Siehe Nachtrag, Gof Singleton ist "böse" wegen den erwähnten Nachteilen, DI nutzt "gute" Singletons, also solche ohne die erwähnten negativen Effekte.


----------



## FArt (4. Jul 2012)

ARadauer hat gesagt.:


> Wiederspricht sich 4 und 5 nicht gewalltig wenn man Anfänger ist?


Wieso widersprechen und gewaltig? Wieso Anfänger?
KISS sollte allgemein gelten und ist relativ. Das erwähnte Singleton Pattern ist ja auch nicht verboten sondern "nur" schlecht. Wenn es die einfachste Lösung ist, dann darf man sie wählen. Man sollte aber gleich darauf hinweisen, dass diese vermeintlich einfache Lösung mehr Nachteile mit sich bringt und somit nicht die beste Wahl ist. Ist eine Lösung "einfacher", weil sie im Code so einfach aussieht? Nein, sie ist (wie man an obigem, falschen Code sieht) fehleranfällig und schlecht zu testen. Vielleicht sollten wir in dem Zusammenhang nicht von DI sondern von IoC reden, das passt vielleicht besser, ist einfach zu realisieren und kommt (mit nur einer Instanz) ohne Singleton Pattern aus. (Übrigens auch ohne Spring, Pico Container, CDI, ...). Es geht auch ganz alt hergebracht mit pure Java.



ARadauer hat gesagt.:


> Wiederspricht sich 4 in sich selbst nicht da eine normale "Spring Bean" ja auch ein Singleton ist?


Spring Bean ist normal und ein Spring Bean als Prototype ist nicht normal? ;-)
Deshalb habe ich "Singleton" bei Punkt 4 in Anführungszeichen geschrieben, zur Unterscheidung vom Singleton Pattern und einer einzelnen Instanz.


----------



## Marco13 (4. Jul 2012)

Ein möglicher Nachteil, je nachdem, wie suggestiv dieses Beispiel war: Man kann bei einer static-Methode keine Polymorphie einsetzen.


----------



## bygones (4. Jul 2012)

ARadauer hat gesagt.:


> Ncihts gegen DI ich arbeite gerne mit Spring. Trotzdem muss man sich bewusst sein, dass man mit Singletons arbeitet. Überhaupt im Web Bereich!


Di ist nicht exklusiv Spring.

Ansonsten - NICHT schon wieder eine Ja-Singleton-Nein-Singleton - gibts dazu nicht schon genuegend threads hier und auf der welt ?!


----------



## FArt (5. Jul 2012)

Marco13 hat gesagt.:


> Ein möglicher Nachteil, je nachdem, wie suggestiv dieses Beispiel war: Man kann bei einer static-Methode keine Polymorphie einsetzen.



Und wo ist der Nachteil ?

Google: prefer delegation over inheritance


----------



## xehpuk (5. Jul 2012)

FArt hat gesagt.:


> Und wo ist der Nachteil ?
> 
> Google: prefer delegation over inheritance


Jau, ohne 
	
	
	
	





```
interface
```
, 
	
	
	
	





```
extends
```
 und 
	
	
	
	





```
implements
```
 wäre alles besser. Und alle Methoden sind immer 
	
	
	
	





```
static
```
. :bahnhof:

Was ich damit sagen will: Dein Einwand war viel zu plump.


----------



## bygones (5. Jul 2012)

xehpuk hat gesagt.:


> Jau, ohne
> 
> 
> 
> ...


er hat recht mit seiner Aussage, auch wenn er diese meiner Ansicht nach ueberzieht. Prefer bedeutet nicht ausschliesslich.

Man sollte auf alle Faelle in Klassen die fuer Vererbung vorgesehen sind auf static nahezu verzichten.


----------



## tfa (5. Jul 2012)

> Und wo ist der Nachteil ?
> 
> Google: prefer delegation over inheritance


Polymorphie ist mehr als nur Vererbung.


----------



## FArt (5. Jul 2012)

tfa hat gesagt.:


> Polymorphie ist mehr als nur Vererbung.


Ich wollte auch nichts anderes behaupten. Ich wollte nur andeuten, dass das nur halb so wild ist, weil in der Regel eh zu oft abgeleitet wird. Und static und Interfaces... da hätte ich auch noch was:

Google: constant interface antipattern

;-)


----------



## tfa (5. Jul 2012)

> Google: constant interface antipattern


Das ist ein Interface, dass nur Konstanten defininiert und keine Methoden. Ich seh hier den Zusammenhang nicht.

Manchmal (je nach Plattform auch relativ häufig) hat man Interfaces, gegen die man entwickeln muss - auch völlig ohne Vererbung. Und da kommt man mit static nicht weit.


----------



## Firephoenix (5. Jul 2012)

Für kleinere Sachen muss man aber auch nicht gleich DI-Frameworks rausholen sondern kann die Objekte auch noch per Hand verschalten 

Ausreichen tut ja schonmal das Konzept, dass man Abhängigkeiten im Konstruktor an mehrere Objekte übergibt, damit spart man sich recht schnell solche Singletons.

Gruß


----------



## huckleberry (12. Jul 2012)

EikeB hat gesagt.:


> Kannst du die Klasse mal zeigen? Muss das wirklich nen Singleton sein?



Ich will die Properties halt bei jedem Aufruf nur ein einzges mal parsen (zu Beginn), ab dann wann es gebraucht wird.. Sag du es mir 


```
package de.utils.configparsers;

import java.io.BufferedWriter;
import java.io.FileInputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Properties;

public final class ConfigReader {

	private static final 	Logger 			LOG = LoggerFactory.getLogger();

	private final static 	String			FILE_CONF = "config.props";
	
	private static 			ConfigReader	_cr = null;
	
	private static 			Properties		_properties = null;
	
	private static 			String 			pathMC;
	private static 			String 			uriConfigFile;
	
	private static 			long			conf_receipt_period = DefaultConstants.RECEIPT_PERIOD ;
	private static 			int				conf_mc_addr = DefaultConstants.MicroCtrllr_ADDR;
	private static 			String 			conf_correct_response = DefaultConstants.RESPONSE_CORRECT_GATEWAY;
	private static 			int 			conf_offset_year = DefaultConstants.OFFSET_YEAR;
	private static 			int 			conf_offset_month = DefaultConstants.OFFSET_MONTH;
	
	
	private ConfigReader(){
        pathMC = System.getProperty("conf.path");
        LOG.logDebug("pathMC {0}", pathMC);
        
        uriConfigFile = pathMC + "/" + FILE_CONF;
        LOG.logDebug("uriConfigFile {0}", uriConfigFile); 

        _properties = new Properties();

	}
	
	public static ConfigReader getInstance(){
		if (_cr == null) _cr = new ConfigReader();
		return _cr;
	}

	public long get_receipt_period() { return conf_receipt_period; }

	public int get_MC_addr() { return conf_mc_addr; }

	public String getCorrect_Response() { return conf_correct_response; }

	public int getOffset_Year() { return conf_offset_year; }

	public int getOffset_Month() { return conf_offset_month; }

	public void parseINI() throws ParseErrorException{
		if (_properties != null) try{
			_properties.load(new FileInputStream(uriConfigFile));
	        
			conf_receipt_period = 	Long.parseLong( _properties.getProperty("RECEIPT_PERIOD") );
	        conf_mc_addr = 			Integer.parseInt( _properties.getProperty("MC_ADDR") );
	        conf_correct_response = _properties.getProperty("RESPONSE_CORRECT_GATEWAY");
	    	conf_offset_year = 		Integer.parseInt( _properties.getProperty("DATE_OFFSET_YEAR") );
	    	conf_offset_month = 	Integer.parseInt( _properties.getProperty("DATE_OFFSET_MONTH") );
		} catch (Exception e) {
			LOG.logError("Excedption @ parseINI(): {0} !!!", e.getLocalizedMessage());
	    } else LOG.logError("_properties is NULL !!!");
	}	
}
```


----------



## maki (12. Jul 2012)

So nebenbei bemerkt, dein Code erinnert mich an eine Mischung aus C und PL/1, Java hat andere Code Conventions


----------



## FArt (12. Jul 2012)

Der Code hat einiges an Macken (nicht nur optisch).

Warum lieferst du ein Singleton (immer noch unsynchronisiert und somit falsch) und parst nicht sofort auch die Properties? So ist die Methode dazu public und kann beliebig oft (und auch konkurrierend) aufgerufen werden.

Die Klasse hat einen ungünstigen Namen (ist kein Reader) und die parse-Methode auch. Die Klasse ist vermutlich eher ein ConfigurationProvider (stellt Konfiguratswerte bereit) und parse sollte private sein und beim Erstellen der Instanz einmalig aufgerufen werden.
So hast du auch das Problem, dass u.U. die Getter vor dem Parsen aufgerufen werden können und somit ein falsches Ergebnis liefern.

In der Regel ist es flexibler, Properties über den Classloader zu laden und nicht aus dem Filesystem.

Streams solltest du immer auch schließen, wenn du mit der Verarbeitung fertig bist.


----------

