Другие ответы, кажется, сосредоточены на объяснении, почему неизменность хороша. Это очень хорошо, и я использую его, когда это возможно. Однако это не ваш вопрос . Я постараюсь ответить на ваш вопрос, чтобы убедиться, что вы получаете ответы и примеры, которые вам нужны.
Я не могу понять, по каким сценариям нам нужен неизменный класс.
«Потребность» - это относительный термин здесь. Неизменяемые классы - это шаблон проектирования, который, как и любая парадигма / шаблон / инструмент, призван облегчить создание программного обеспечения. Точно так же много кода было написано до появления парадигмы ОО, но причислите меня к числу программистов, которые «нуждаются» ОО. Неизменяемые классы, такие как ОО, не являются строго необходимыми , но я буду действовать так, как будто они мне нужны.
Вы когда-нибудь сталкивались с таким требованием?
Если вы не смотрите на объекты в проблемной области с правильной точки зрения, вы можете не увидеть требование для неизменяемого объекта. Может быть легко подумать, что проблемный домен не требует каких-либо неизменных классов, если вы не знаете, когда их использовать выгодно.
Я часто использую неизменные классы, в которых я рассматриваю данный объект в моей проблемной области как значение или фиксированный экземпляр . Это понятие иногда зависит от перспективы или точки зрения, но в идеале будет легко переключиться на правильную перспективу, чтобы идентифицировать хорошие объекты-кандидаты.
Вы можете лучше понять, где неизменные объекты действительно полезны (если в этом нет особой необходимости), убедившись, что вы читаете различные книги / онлайн-статьи, чтобы развить хорошее понимание того, как думать о неизменные классы. Хорошая статья для начала - Теория и практика Java: мутировать или не мутировать?
Я попытаюсь привести пару примеров ниже, как можно видеть объекты в разных ракурсах (изменяемые и неизменяемые), чтобы прояснить, что я имею в виду под перспективой.
... не могли бы вы привести какой-нибудь реальный пример, где мы должны использовать этот шаблон.
Поскольку вы попросили реальные примеры, я дам вам несколько, но сначала давайте начнем с некоторых классических примеров.
Классические объекты значения
Строки и целые числа и часто рассматриваются как значения. Поэтому неудивительно, что класс String и класс-обертка Integer (а также другие классы-обертки) неизменны в Java. Цвет обычно рассматривается как значение, то есть неизменный класс Color.
Контрпример
Напротив, автомобиль обычно не считается ценным объектом. Моделирование автомобиля обычно означает создание класса с изменяющимся состоянием (одометр, скорость, уровень топлива и т. Д.). Однако есть некоторые домены, где это может быть ценным объектом. Например, автомобиль (или, в частности, модель автомобиля) может рассматриваться как объект стоимости в приложении для поиска подходящего моторного масла для данного транспортного средства.
Игральные карты
Вы когда-нибудь писали программу для игральных карт? Я сделал. Я мог бы представить игральную карту как изменчивый объект с изменяемой мастью и рангом. Рука с дро-покер может быть в 5 фиксированных случаях, когда замена 5-й карты в моей руке будет означать превращение 5-го экземпляра игральной карты в новую карту путем изменения ее масти и ранга Ивара.
Тем не менее, я склонен думать об игральной карте как о неизменном объекте, который имеет фиксированную неизменную масть и звание после создания. Моя рука в покерном розыгрыше будет 5 экземпляров, и замена карты в моей руке будет означать сброс одного из этих экземпляров и добавление нового случайного экземпляра в мою руку.
Карта проекции
Последний пример - когда я работал над кодом карты, где карта могла отображаться в различных проекциях .В исходном коде карта использовала фиксированный, но изменяемый экземпляр проекции (как изменяемая игральная карта выше).Изменение проекции карты означало изменение иваров экземпляра проекции карты (тип проекции, центральная точка, увеличение и т. Д.).
Однако я чувствовал, что дизайн был проще, если я думал о проекции как о неизменном значении или фиксированном экземпляре,Изменение проекции карты означало, что карта ссылается на другой экземпляр проекции, а не изменяет фиксированный экземпляр проекции карты.Это также упростило захват именованных проекций, таких как MERCATOR_WORLD_VIEW
.