on
아이템17. 변경 가능성을 최소화하라
아이템17. 변경 가능성을 최소화하라
728x90
불변 클래스란 인스턴스의 내부 값을 변경할 수 없는 클래스
String, 기본 타입의 박싱 된 클래스들, BigInteger, BigDecimal 등
불변 클래스는 가변 클래스보다 설계, 구현, 사용이 쉽고 오류 발생 여지가 적음
불변 클래스는 다음 5가지 규칙을 따른다.
1. 객체의 상태를 변경하는 메서드(변경자; setter)를 제공하지 않음
2. 클래스 확장 금지
하위 클래스에서 객체 상태를 변하게 만드는 사태를 막아야 한다. 상속을 막는 대표적인 방법은 클래스를 final로 선언하는 것
3. 모든 필드는 final로 선언
시스템이 강제하는 수단을 이용해 설계자의 의도를 명확히 드러내는 방법임
4. 모든 필드를 private로 선언
필드가 참조하는 가변 객체를 클라이언트에서 직접 접근, 수정하는 일을 막음
5. 자신 외에는 내부 가변 컴포넌트에 접근할 수 없도록 방지
클래스에 가변 객체를 참조하는 필드가 있다면 클라이언트에서 그 객체의 주소를 얻을 수 없도록 해야 함
4번의 이유와 유사하게 클라이언트에서 변형하는 일을 막는 목적
public final class Complex { private final double re; private final double im; public Complex(double re, double im) { this.re = re; this.im = im; } public double realPart() {return re;} public Complex plus(Complex c) { return new Complex(re + c.re, im + c.im); } }
여기서 사칙연산 메서드들은 인스턴스 자신을 수정하지 않고 새로운 Complex 인스턴스를 만들어 반환한다.
피연산자에 함수를 적용해 결과를 반환하지만 피연산자 자체는 그대로인 프로그래밍 패턴을 함수형 프로그래밍이라 한다. 반대로 절차적 또는 명령형 프로그래밍에서는 피연산자인 자신을 수정해 자신의 상태가 변한다.
불변 객체는 생성된 시점의 상태가 파괴될 때까지 그대로 존재하기 때문에 단순하다.
불변 클래스는 자주 사용되는 인스턴스를 캐싱하여 같은 인스턴스를 중복 생성하지 않게 해주는 정적 팩토리를 제공할 수 있다.
박싱 된 기본 타입 클래스 전부와 BigInteger가 여기에 속함
장점
불변 객체를 자유롭게 공유할 수 있다는 점은 방어적 복사도 필요 없다는 뜻이다. 복사를 해봐야 원본과 동일하기 때문에 복사 후 제공의 의미가 없다.
불변 객체는 그 자체로 실패에 대해 원자성을 제공
단점
값이 다르면 반드시 독립된 객체로 생성해야 함
클래스가 불변임을 보장하려면 상속하지 못하게 막아야 하는데 가장 쉬운 방법은 final class로 선언하는 것이지만 모든 생성자를 private나 package-private로 만들고 public 정적 팩토리를 제공하는 방법이 더 유연함
1) 생성자 대신 정적 팩토리 메소드를 고려하라.
요약
클래스는 꼭 필요한 경우가 아니라면 불변이 좋음
불변으로 만들 수 없는 클래스라도 변경할 수 있는 부분을 최소한으로 줄이기
특별한 이유가 없다면 클래스 내 필드는 private final로 선언
java.util.concurrent 패키지의 CountDownLatch 클래스가 이러한 원칙을 잘 방증한 케이스
728x90
from http://development-record.tistory.com/98 by ccl(A) rewrite - 2021-11-17 01:27:40