정리용/java
[JAVA] 기초 2. 생성 방법 3가지 - (3) 정적 팩토리 메서드
hee-ya07
2025. 1. 23. 17:01
3. 정적 팩토리 메서드
:: 객체를 생성할 수 있는 방법을 단 하나의 정적 메서드 방식으로만 가능하게 제한
- 팩토리 메서드(Factory Method Pattern)
:: 캡슐화된 Factory 클래스가 대리하여 객체 생성 및 반
:: 클라이언트에서 new 키워드를 통한 생성 X - 정적 메서드의 의의 => 기존 객체에서 새로운 객체로의 변환
// 생성자를 Lombok 어노테이션으로 private 설정 가능
@NoArgsConstructor(access = AccessLevel.PRIVATE)
@AllArgsConstructor(access = AccessLevel.PRIVATE)
// 적용
@AllArgsConstructor(access = AccessLevel.PRIVATE)
public class Member {
private Integer id;
private String name;
private int age;
private String email;
public static Member from(MemberCreateRequestDto requestDto) {
return new Member(
null,
requestDto.getName(),
0,
requestDto.getEmail()
);
}
}
MemberCreateRequestDto requestDto = new MemberCreateRequestDto("Baron", "baron@example.com");
// 생성자가 Private 가 되었으므로 외부에서 호출이 불가 -> 메서드로 대체
Member baron = Member.from(requestDto);
3.1 정적 메서드를 통한 객체 생성의 장점
1) 메서드가 이름을 가질 수 있음 -> 시멘틱이 명확
2) 호출마다 새 객체를 생성할 필요가 없어짐 (-> 생성 객체 수 제한)
3) 하위 자료형 객체를 반환 가능 -> 상속 사용 시의 이점, but 보통은 조합을 사용하기에 체감은 낮음
4) 객체 생성의 캡슐화 가능 -> 생성자도 가능...
3.2 싱글톤 패턴(Singleton Pattern)
:: 하나의 클래스에 대해 단 하나의 인스턴스만 생성되도록 보장
:: 해당 인스턴스에 전역적으로 접근할 수 있게 하는 패턴
- 구현
더보기
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public class Member {
private static Member instance; // 하나의 인스턴스만을 공유하도록 static 사용
protected Integer id;
protected String name;
protected int age;
protected String email;
public static Member getInstance() { // 외부에서 사용하는 메서드
if (Objects.isNull(instance)) {
instance = new Member();
}
return instance;
}
}
- 단점 :: 멀티 스레드 환경에서 if문에 동시 접근 시, 예상치 못한 오류가 발생할 가능성 존재
- 해결 1
:: 함수 단위 Bloacking으로 동시성 문제 해결
:: synchronized
- 구현
더보기
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public class Member {
private static Member instance;
protected Integer id;
protected String name;
protected int age;
protected String email;
public synchronized static Member getInstance() { // sysnchronized를 통해 동시 접근 방어
if (Objects.isNull(instance)) {
instance = new Member();
}
return instance;
}
}
- 단점 :: syschronized는 동기적으로 작동하므로 성능저하를 불러옴
- 해결 2
:: 변수 생성 단위 Blacking으로 동시성 문제 해결
:: volatile + synchronized
:: volatile을 통해 JVM은 해당 변수를 복사가 아닌 주메모리에서 확인하고 사용-> 가시성 보장
- 구현
더보기
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public class Member {
private volatile static Member instance; // volatile키워드
protected Integer id;
protected String name;
protected int age;
protected String email;
public static Member getInstance() {
synchronized (Member.class) { // 멀티 스레드에서 동시 접근 방어
if (Objects.isNull(instance)) {
instance = new Member();
}
}
return instance;
}
}
- 단점 :: 주메모리에 접근에 따른 비용 증가 및 여전히 동기적으로 작동하므로 성능저하를 불러옴
- 해결 3
:: Bill Pugh Singleton Design
:: 정적 내부 클래스 로딩 시, 인스턴스를 초기화(지연 초기화)
:: getInstance()를 통해서만 인스턴스 반환 및 관리
- 구현
더보기
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public class Member {
private static class LazyHolder {
private static final Member UNIQUE_INSTANCE = new Member();
}
protected Integer id;
protected String name;
protected int age;
protected String email;
public static Member getInstance() {
return LazyHolder.UNIQUE_INSTANCE;
}
}
참고
ASAC 수업자료