-
정적 팩터리 메서드 : static 팩토리 메서드를 의미
-
new 연산자를 통한 객체 생성은 자원을 낭비함, new 를 사용하면 heap영역에 항상 메모리 공간이 확보됨
-
따라서, 객체를 효율적으로 생성하기 위해서 정적 팩터리 메서드 사용
-
장점
- (1) 이름을 갖음 - 메서드 여러개 만들 수 있음
- (2) 인스턴스 재사용 - 불필요하게 인스턴스를 반복해서 생성할 필요 없이 재사용할 수 있음(flyweight 패턴)
- (3) 다형성, 공변이 가능함 - 반환할 클래스를 자유롭게 선택 가능. 예를 들어, Car car = CarFactory.getInstance("sportCar");
- (4) 매개변수에 따라 다른 객체 반환 - CarFactory.getInstance("truck"), CarFactory.getInstance("sportCar"), ...
- (5) 정적 팩터리 메서드를 작성할 때, 반환 객체 클래스가 존재하지 않아도됨 - Future 패턴과 유사(빈 박스제공)
-
단점
- (1) 상속 불가능 - 생성자가 private 이기 때문
- (2) 메서드 찾기 어려움 - 이름이 여러개임
- 빌더 패턴 : "생성자에 매개변수가 많음 -> 생성자 오버로딩 많이함, 매개변수 순서 혼동" 해결하기 위해 내부적으로 빌더 클래스를 정의해서 해당 클래스를 생성할 때 사용
- 싱글톤 : 인스턴스 하나만 생성하고 공유
- 구현 방법 - (1) public static final -> (2) 정적 팩터리 메서드 -> (3) 열거형
- 굳이 이렇게 까지 할 필요는 없음, 물론 싱글톤같은 디자인 패턴에는 적용해야함
- 전략 패턴, 알고리즘을 외부에서 통째로 넣어줌
- 예시에서 나온 맞춤법 검사기의 문제점은 "자주 변경될 부분이 구체적으로 작성되어 있음"
- 예를 들어, 언어마다 맞춤법이 다르기 때문에 해당 부분을 쉽게 변경할 수 있게 구현해야함(전략 패턴)
- 멀티 쓰레드 환경도 고려해야함
- 재사용 가능한 객체라는 의미는 공유 가능한 정보를 갖고 있냐도 포함임
- 즉, 내부 iv가 불변이 아닌 경우, 또한 동기화 처리가 안되있는 경우는 멀티 쓰레드 환경에서 공유해서 사용할 경우 프로그램에 혼동을 야기할 수 잇음
- 가비지 컬렉터가 사용되지 않는 객체를 회수하지만, 100% 회수해주지 않음
- 참조가 걸려있지만 사용하지 않는 경우에는 회수하지 못함
- 대표적으로 Flyweight 패턴에서 맵에 저장된 안쓰는 객체 회수 못함
- 위와 같은 경우는 개발자가 참조를 해제해야함
-
핵심은 "구체 클래스를 확장해 새로운 값을 추가하면서 equals() 규약을 만족시킬 방법은 존재하지 않는다."
-
equals()를 오버라이딩 하지 않아야하는 상황
- (1) 각 인스턴스는 고유함 : 기본적으로 참조 비교가 정상임
- (2) 인스턴스의 '논리적 동치성'을 검사할 일이 없음 : 값 비교(논리적 동치성)를 의미함
- (3) 조상에서 재정의한 equals()가 자손에서도 딱 들어맞는다
- 조상, 자손은 iv의 개수가 같거나 다름
- 자손에서 iv가 추가되고 equals()를 오버라이딩 하면 문제가 발생
- 동치관계(빈사성, 대칭성, 추이성, 일관성, null-아님) 충족 못함
- 양질의 equals()를 오버라이딩 하기 위한 규칙
- (1) == 연산자를 사용해 입력이 자기 자신인지 확인
- (2) instanceof 를 통해 타입 확인
- (3) 대응되는 '핵심' 필드들이 모두 일치하는지 하나씩 확인
- (4) 대칭적? 추이성? 일관적? 스스로 자문
- 핵심은 "equals()를 재정의한 클래스 모두 hashCode를 재정의해야함"
- 같은 객체는 같은 해시코드를 반환해야 하기 때문
- 해시코드(hashCode) : 디지털 지문, 디지털 증거용으로서 많이 사용함, 파일을 건드리면 디지털 지문이 변경됨
- 해시코드를 얻기 위해 호출할 때 마다 해시 값을 매번 계산할 필요 없음
- 한번만 계산하고 저장 해두었다가 그 값을 반환
- 해시값은 불변
- hashCode() 메서드의 경우, 스레드 안정성까지 고려해야함
- 기본적으로, 클래스_이름@16진수_해시코드
- 모든 하위 클래스에서 toString을 재정의, 그 객체가 가진 주요 정보 모두 반환
- 디버깅 용이
- 객체 정보 파악 용이
- Cloneable 인퍼테이스, clone 가능한 클래스 임을 의미
- clone은 원본 객체에 영향 x, 복제된 객체의 불변식을 보장해야함
- 주의할 점
- 깊은 복사 vs 얕은 복사
- 동기화 처리
- 복사 생성자, 복사 팩터리 활용 할 수 있음
- 왠만하면 "복제 기능은 생성자와 팩터리를 이용하는게 좋음"
- 기본 비교 기준, 기본 비교 기준 이외 Comparator로 구현
- 동치성 + 순서 비교, 객체의 순서 비교
- 반사성, 대칭성, 추이성 충족
- <와 >는 추천하지 않음, == 과 compareTo() 활용