불변 객체(Immutable Object)는 한 번 생성되면 그 상태를 변경할 수 없는 객체를 의미한다
주요 특징
- 상태 불변성: 객체가 생성된 이후에는 객체의 상태(필드 값)를 변경할 수 없다. 모든 필드는 초기화된 후에 변하지 않으며, 수정이 불가능하다.
- 단순성: 불변 객체는 상태 관리가 단순하다. 상태가 변하지 않으므로, 복잡한 상태 변경 로직을 고려할 필요가 없다.
불변 객체의 예
- Java의 String 클래스: String 객체는 불변 객체의 대표적인 예이다. String 객체가 생성된 후에는 해당 문자열의 내용을 변경할 수 없다. 문자열을 조작하는 메서드(예: concat, replace)는 항상 새로운 String 객체를 반환하며, 기존 객체는 변하지 않는다.
- 래퍼 클래스 (Integer, Double, Boolean 등): 기본형 타입을 객체로 감싸는 래퍼 클래스도 불변 객체이다. 예를 들어, Integer 객체는 생성된 이후에 그 값을 변경할 수 없다.
불변 객체를 만드는 방법
- 모든 필드를 final로 선언: 필드를 final로 선언하면, 객체가 생성될 때 필드가 반드시 초기화되고, 이후에는 값을 변경할 수 없다.
- 필드를 private으로 선언: 외부에서 직접 필드에 접근하여 변경할 수 없도록 필드를 private으로 선언한다.
- Setter 메서드 제공 금지: 필드 값을 변경할 수 있는 Setter 메서드를 제공하면 안 된다.
- 생성자에서 모든 필드 초기화: 모든 필드를 한 번만 초기화하도록 생성자에서 값을 설정한다.
- 가변 객체를 필드로 사용하지 않기: 불변 객체 내에서 가변 객체(예: List, Map, Date)를 필드로 사용해야 한다면, 이 필드를 변경할 수 없도록 조치해야 한다. 예를 들어, 가변 객체의 복사본을 생성해 필드로 저장하거나, 가변 객체의 불변 버전을 사용하는 방식으로 처리할 수 있다.
불변 객체의 활용
- 캐시: 캐시 일관성을 유지하는 데 도움을 주며, 캐시에서의 히트율을 높일 수 있다. 또한, 불변 객체는 동일한 상태를 가지는 객체를 여러 번 생성하지 않고, 캐시된 객체를 재사용할 수 있어 메모리 효율성도 높다.
- 멀티스레드: 불변 객체는 여러 스레드가 동시에 접근하더라도 상태가 변경되지 않기 때문에, 추가적인 동기화 없이도 스레드로부터 안전하다.
- 엔티티의 값 타입: 값 타입이란, 객체의 동일성을 참조하는 것이 아니라 그 내용 자체가 동일한지를 확인하는 타입을 의미한다. 불변 객체는 상태가 변경되지 않으므로, 동일한 값에 대해 동일한 결과를 보장할 수 있다. 예를 들어, 두 개의 불변 객체가 같은 값을 가지면, 이 둘은 동일한 것으로 간주될 수 있다. 이로 인해, 불변 객체는 값 타입으로 사용할 때 객체의 상태 변화로 인한 예기치 않은 동작을 방지할 수 있으며, 코드의 예측 가능성을 높인다.
※ 불변 객체에서 값을 변경하는 경우 withYear()처럼 "with"로 시작하는 경우가 많다.
예를 들어 "coffee with sugar"라고 하면, 커피에 설탕이 추가되어 원래의 상태를 변경하여 새로운 변형을 만든다는 것을 의미한다.
이 개념을 프로그래밍에 적용하면, 불변 객체의 메서드가 "with"로 이름 지어진 경우, 그 메서드가 지정된 수정사항을 포함하는 객체의 새 인스턴스를 반환한다는 사실을 뜻한다.
정리하면 "with"은 관례처럼 사용되는데, 원본 객체의 상태가 그대로 유지됨을 강조하면서 변경사항을 새 복사본에 포함하는 과정을 간결하게 표현한다.
참고 및 출처: 김영한의 실전 자바 - 중급 1편
'소프트웨어공학 > OOP' 카테고리의 다른 글
[OOP] 리플렉션(reflection) (0) | 2024.08.23 |
---|---|
[OOP] 메서드 체이닝(Method Chaining) (0) | 2024.08.22 |
[OOP] 정적 의존관계 vs 동적 의존관계 (0) | 2024.08.20 |
[OOP] OCP(개방 폐쇄 원칙)과 디자인 패턴 (0) | 2024.08.12 |
[OOP] UML 표기법 (0) | 2024.08.09 |