Избегайте создания экземпляра класса в java
Недавно я столкнулся с вопросом: как избежать создания экземпляра класса Java?
Однако, я ответил, сказав:
-
Если вы не хотите создавать экземпляр класса, используйте "абстрактный" модификатор. Пример: javax.servlet.HttpServlet, объявлен как абстрактный (хотя ни один из его методов не является абстрактным), чтобы избежать создания экземпляра.
-
Объявить закрытый конструктор без аргументов.
Теперь мой вопрос:
а) есть ли другие способы?
б) почему кто-то не хочет создавать экземпляр класса? - после поиска в SO, я узнал из этого, что классы Util могут быть созданы не для создания экземпляра. В других местах, где мы не хотим создавать экземпляр класса в ООП?
Ответы
Ответ 1
Четыре причины spring:
- Чтобы разрешить создание подклассов, но не родительский;
- Чтобы запретить создание direct и вместо этого предоставить метод factory для возврата и при необходимости создать экземпляры;
- Потому что все экземпляры предопределены (например, костюмы в колоде карт), хотя, поскольку Java 5 рекомендуется вместо них перечислять типы имен, и
- Класс действительно не является классом. Это просто держатель для статических констант и/или методов.
В качестве примера (2) вы можете создать канонические объекты. Например, цветовые комбинации RGB. Вы не хотите создавать более одного экземпляра любой комбинации RGB, чтобы вы это сделали:
public class MyColor {
private final int red, green, blue;
private MyColor(int red, int green, int blue) {
this.red = red;
this.green = green;
this.blue = blue;
}
public static MyColor getInstance(int red, int green, int blue) {
// if combo already exists, return it, otherwise create new instance
}
}
Примечание. конструктор no-arg не требуется, поскольку явно определен другой конструктор.
Ответ 2
Не совсем ответ на ваш вопрос, а просто примечание:
Когда вы создаете закрытый конструктор no-arg для предотвращения создания экземпляров ваших классов утилиты, вы должны создать конструктор для исключения (например, UnsupportedOperationException). Это связано с тем, что вы можете получить доступ к частным членам (включая конструкторы) через отражение. Обратите внимание, что если вы это сделаете, вы должны сопроводить его комментарием, потому что он немного противоречит интуиции, что вы определяете конструктор предотвращать класс от экземпляра.
Создание абстрактного класса утилиты не является хорошей идеей, потому что это делает класс похожим на то, что он предназначен для расширения, и, кроме того, вы можете расширить класс и тем самым создать его экземпляр.
Ответ 3
Иногда вам нужно избегать других экземпляров объектов, чтобы иметь полный контроль над всеми существующими экземплярами. Одним из примеров является singleton pattern.
Ответ 4
Я думаю, что самая распространенная причина не желать создавать экземпляр класса - это когда вы имеете дело со статическим классом и, следовательно, с его статическими методами. Вы не хотите, чтобы кто-то пытался создать экземпляр этого класса. Аналогично, когда вы имеете дело с классами Factory или в некоторых случаях многие одноэлементные классы будут скрывать свой конструктор, чтобы он не был инстанцирован обычным способом.
Ответ 5
Другой способ сделать класс неинтересным - объявить его как частный внутренний класс, а затем не предоставлять никакого способа его создания в окружающем классе. Но это (IMO) довольно бессмысленно.
Вы хотите, чтобы класс был несовместимым, если нет смысла его создавать. Обычно вы это делаете, если класс действительно представляет собой набор (статических) вспомогательных методов или если класс "неполный". Незавершенность может быть синтаксически очевидной (т.е. Абстрактными методами), но есть и другие виды незавершенности. Например, вы можете предоставить стандартные реализации по умолчанию для всех методов и потребовать, чтобы один или несколько из них были переопределены для класса, чтобы сделать что-то полезное.
Еще одна причина сделать класс неинтуитивным (или, по крайней мере, не прямодействующим) - это если ваше приложение должно контролировать экземпляр. Например, класс java.util.regex.Pattern не может быть напрямую создан, чтобы JRE мог (может) поддерживать кэш предварительно скомпилированных регулярных выражений.