Klasy użytkowe
Prawie w każdym projekcie pojawia się przynajmniej jedna klasa, która gromadzi metody użytkowe wspomagające działanie aplikacji. Taką klasę nazywamy najczęściej klasą pomocniczą (ang. utility class).Składa się ona z kilku/kilkunastu metod statycznych używanych w różnych miejscach aplikacji. Taka klasa nie powinna umożliwiać tworzenia swojej instancji, gdyż jest to zbędne.
Bardzo łatwo możemy wymusić takie zachowanie na innych programistach tworząc konstruktor prywatny:
public class Utils {
/*
* This is utility class, you don't have to create instance to use it
*/
private Utils() { }
public static String prepareUserStringForEmail(User user) {
// ...
}
public static String createRandomString(int length) {
// ...
}
public static String formatDateWithTime(Date date) {
// ...
}
}
Dzięki takiemu prostemu zabiegowi, nasz kod zyskał na czytelności, a inni programiście nie będą używać naszej klasy w sposób niepoprawny.
Optymalizowanie tworzenia obiektów, których używamy wielokrotnie
Przyjrzyjmy się poniższemu fragmentowi pewnej klasy:
public class Utils {
/*
* This is utility class, you don't have to create instance to use it
*/
private Utils() { }
public static boolean isOlderThanCodeHardGoProBlogOwner(Date birthDate) {
if(birthDate == null) {
throw new IllegalArgumentException("Date can not be null");
}
Calendar calendar = Calendar.getInstance();
calendar.set(1984, Calendar.JULY, 22);
Date codeHardGoProOwnerDateOfBirth = calendar.getTime();
return birthDate.compareTo(codeHardGoProOwnerDateOfBirth) < 0;
}
}
Sprawdzamy tutaj, czy czyjaś data urodzin jest wcześniejsza niż moja. Tworzymy obiekt klasy Calendar, ustawiamy mu odpowiednie wartości roku, miesiąca i dnia, a następnie porównujemy ze zmienną birthDate.
Gdy wywołamy metodę kolejny raz, obiekt calendar zostanie utworzony ponownie i zostanie mu ustawiona ta sama data co poprzednio. Nie jest to rozwiązanie najbardziej optymalne. Widać tutaj wyraźnie, że tworzenie obiektu calendar i ustawianie mu odpowiedniej wartości powinno zostać wydzielone poza metodę i wykonywane tylko raz. Efekt taki możemy uzyskać przenosząc fragment kodu do bloku statycznego, a zmienną klasy Date uczynić prywatną i statyczną:
public class Utils {
private final static Date CODE_HARD_GO_PRO_BLOG_OWNER_BIRTH_DATE;
static {
Calendar calendar = Calendar.getInstance();
calendar.set(1984, Calendar.JULY, 22);
CODE_HARD_GO_PRO_BLOG_OWNER_BIRTH_DATE = calendar.getTime();
}
private Utils() { }
public static boolean isOlderThanCodeHardGoProBlogOwner(Date birthDate) {
if(birthDate == null) {
throw new IllegalArgumentException("Date can not be null");
}
return birthDate.compareTo(CODE_HARD_GO_PRO_BLOG_OWNER_BIRTH_DATE) < 0;
}
}
Teraz nasza metoda będzie wykonywała się trochę szybciej. Oczywiście zysk będzie znacznie większy, gdy taki wielokrotnie używany obiekt będzie bardziej skomplikowany, a jego tworzenie kosztowniejsze i bardziej czasochłonne.
A czemu nie po prostu:
OdpowiedzUsuńprivate final static Date CODE_HARD_GO_PRO_BLOG_OWNER_BIRTH_DATE = new GregorianCalendar(1984, Calendar.JULY, 22).getTime();
Przenośność?
Faktycznie Twój sposób wydaje się lepszy niż podany przez autora. Zastanawiam się dlaczego w książce nie zaproponowano właśnie takiego rozwiązania. Być może chodzi właśnie o potencjalną przenośność pomiędzy różnymi kalendarzami (żydowski, muzułmański, itp.), choć to trochę wydumany powód. A może po prostu poprawność polityczna nakazywała jawnie nie faworyzować w książce jednego kalendarza ponad inne? :)
OdpowiedzUsuń