Mam klasę pełną funkcji użytkowych. Tworzenie instancji tego nie ma sensu semantycznego, ale nadal chcę wywoływać jego metody. Jak najlepiej sobie z tym poradzić? Klasa statyczna? Abstrakcyjny?
Mam klasę pełną funkcji użytkowych. Tworzenie instancji tego nie ma sensu semantycznego, ale nadal chcę wywoływać jego metody. Jak najlepiej sobie z tym poradzić? Klasa statyczna? Abstrakcyjny?
Odpowiedzi:
Prywatny konstruktor i metody statyczne w klasie oznaczonej jako ostateczna.
Według wielkiej książki „Effective Java” :
Punkt 4: Wymuszaj nieinstanowalność za pomocą prywatnego konstruktora
- Próba wymuszenia nieinstancji poprzez tworzenie abstrakcji klasy nie działa.
- Domyślny konstruktor jest generowany tylko wtedy, gdy klasa nie zawiera jawnych konstruktorów, więc klasę można uczynić nieinstanowalną, dołączając konstruktor prywatny:
// Noninstantiable utility class
public class UtilityClass
{
// Suppress default constructor for noninstantiability
private UtilityClass() {
throw new AssertionError();
}
}
Ponieważ jawny konstruktor jest prywatny, jest niedostępny poza klasą. AssertionError nie jest ściśle wymagane, ale zapewnia ubezpieczenie na wypadek, gdyby konstruktor został przypadkowo wywołany z poziomu klasy. Gwarantuje, że klasa nigdy nie zostanie utworzona w żadnych okolicznościach. Ten idiom jest nieco sprzeczny z intuicją, ponieważ konstruktor jest dostarczony wyraźnie, więc nie można go wywołać. Dlatego rozsądnie jest zamieścić komentarz, jak pokazano powyżej.
Jako efekt uboczny ten idiom zapobiega również podklasie klasy. Wszystkie konstruktory muszą wywoływać konstruktor nadklasy, jawnie lub niejawnie, a podklasa nie miałaby dostępnego konstruktora nadklasy do wywołania.
AssertionError
na inne alternatywy, takie jak IllegalStateException
, UnsupportedOperationException
itp?
Wygląda na to, że masz klasę narzędziową podobną do java.lang.Math .
Podejście to ostatnia klasa z prywatnym konstruktorem i metodami statycznymi.
Ale uważaj na to, co to robi dla testowalności, polecam przeczytanie tego artykułu
Static Methods are Death to Testability
Aby płynąć pod prąd, statyczni członkowie i klasy nie uczestniczą w OO i dlatego są źli. Nie, nie jest zły, ale poważnie, poleciłbym zwykłą klasę z pojedynczym wzorcem dostępu. W ten sposób, jeśli musisz zmienić zachowanie w jakimkolwiek przypadku na drodze, nie jest to poważna zmiana narzędzi. OO jest twoim przyjacielem :-)
Moje .02
skomentuj argumenty „prywatnego konstruktora”: daj spokój, programiści nie są tacy głupi; ale są leniwi. tworzenie obiektu, a następnie wywołanie metod statycznych? nie wydarzy się.
nie trać zbyt wiele czasu, aby upewnić się, że Twoja klasa nie zostanie niewłaściwie wykorzystana. miej wiarę w swoich kolegów. i zawsze istnieje sposób na niewłaściwe wykorzystanie Twojej klasy, bez względu na to, jak ją chronisz. jedyną rzeczą, której nie można nadużyć, jest rzecz całkowicie bezużyteczna.
Nie ma sensu deklarować klasy jako static
. Po prostu zadeklaruj jego metody static
i wywołaj je z nazwy klasy w normalny sposób, jak klasa Math w Javie .
Ponadto, mimo że nie jest absolutnie konieczne, aby konstruktor był prywatny, warto to zrobić. Oznaczenie konstruktora jako prywatnego uniemożliwia innym osobom tworzenie wystąpień Twojej klasy, a następnie wywoływanie metod statycznych z tych wystąpień. (Te wywołania działają dokładnie tak samo w Javie, po prostu wprowadzają w błąd i szkodzą czytelności kodu).
Możesz użyć adnotacji @UtilityClass z lombok https://projectlombok.org/features/experimental/UtilityClass