Nicht-instantiierbare Klassen

Moin,

in einer geschlossenen Anwendung, würde ich die oben erwähnten Utility-Klassen etwa so implementieren:

Interface:



public interface Utilities {

    /**
     * Do some magic
     * 
     * @param input
     * @return
     */
    int method(final int input);

}```

Implementierung:
```package net.mschorn.kskb.utilities;

import javax.inject.Inject;
import javax.inject.Singleton;

@Singleton
public final class UtilitiesImpl implements Utilities {

    private static final int MAGIC = 42;


    @Inject
    private UtilitiesImpl() {

    }


    @Override
    public int method(final int input) {

        return input * MAGIC;

    }


}

Verwendung der Utility-Methode:


import javax.inject.Inject;

import net.mschorn.kskb.utilities.Utilities;


public final class Use {

    private final Utilities utilities;


    @Inject
    private Use(final Utilities utilities) {

        this.utilities = utilities;

    }


    public int use(final int input) {

        return utilities.method(input) + 7;

    }


}```

Und im Test sähe das dann etwa so aus:

Test für die Utility-Methode:
```package net.mschorn.kskb.utilities;

import static org.testng.Assert.assertEquals;
import mockit.Tested;

import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;


public final class UtilitiesImplTest {


    @Tested
    private UtilitiesImpl utilities;


    @DataProvider(name = "method")
    public Object[][] createData() {

        return new Object[][] {
                { 0, 0 },
                { 1, 42 },
                { 2, 84 }
        };

    }


    @Test(dataProvider = "method")
    public void method(final int input, final int expected) {

        assertEquals(utilities.method(input), expected);

    }


}```

Test des Verwenders mit Mock der Utility-Klasse:
```package net.mschorn.kskb.main;

import static org.testng.Assert.assertEquals;
import mockit.Expectations;
import mockit.Injectable;
import mockit.Tested;
import net.mschorn.kskb.utilities.Utilities;

import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;

public final class UseTest {

    @Tested
    private Use use;

    @Injectable
    private Utilities utilities;


    @DataProvider(name = "use")
    public Object[][] createData() {

        return new Object[][] {
                { 0, 7 },
                { 1, 8 },
                { 2, 9 }
        };

    }


    @Test(dataProvider = "use")
    public void use(final int input, final int expected) {

        new Expectations() {

            {
                utilities.method(input);
                returns(input);
            }

        };

        assertEquals(use.use(input), expected);

    }


}```


So entsteht natürlich etwas Tipparbeit, aber es ist einfach zu schreiben, einfach zu testen und skaliert beliebig. Problematisch kann es werden, wenn man das so in einer offenen Library implementiert, da man den Verwender zu DI zwingt. Ob das wirklich immer ein Nachteil ist, weiß ich aber nicht.

Viele Grüße
Fancy

[QUOTE=schlingel]Naja, man kennt es schon. Ich hab’ dieses Semester Markus Struberg als Vortragenden in einer Lehrveranstaltung. (Entwickler CDI, OpenWebBeans, etc.) Der hat dieses Pattern auch kurz erwähnt als es um Singletons-Implementierungen ging.

Diese ganze Lösungen haben alle Vor- und Nachteile die über Stilfragen hinausgehen. Da sie sich auch puncto ClassLoading/Veränderbarkeit anders verhalten können.

Irgendwer hat’s eh schon erwähnt. Java stellt hier einfach keine probate Mittel zur Verfügung das zu implementieren ohne dass sich hier Kritikpunkte ergeben würden.[/QUOTE]
Es gibt doch ein probates Mittlel: privater Konstruktor und gut.

Und Singletons in einer EE-Umgebung so abzubilden ist ziemlicher Mist.

Was erspart einem das verwenden von static bzw. statischen Utility Methoden/Klassen nochmal bzw. das vermeiden von Instanzen?
Diskussionen über das „wie implmentieren“ sicher nicht :wink: