728x90
반응형
정적 팩토리 메서드(Static Factory Method)는 객체를 생성하는 정적 메서드를 의미한다. 일반적으로 생성자를 호출하는 대신, 클래스가 제공하는 정적 메서드를 통해 객체를 생성하는 방식이다. new 키워드를 직접적으로 사용하지 않고, 내부적으로 이를 활용하여 객체를 반환한다.
- 특징
- new를 직접적으로 사용하지 않을 뿐, 정적 메서드이므로 클래스의 인스턴스를 생성하지 않고 호출할 수 있다.
- 생성자 호출과 동일하게 객체를 생성하지만, 추가적인 기능을 제공하거나 제약을 줄 수 있다.
* new를 직접적으로 사용하지 않을 뿐, 클래스의 인스턴스를 생성하지 않고 호출할 수 있다. 정적 팩토리 메서드라는 클래스 내에서 선언되어 있는 메서드를 내부의 new를 이용해 객체를 생성해 반환하는것, 즉 정적 팩토리 메서드를 통해 new를 간접적으로 사용하는 것이다.
1. 정적 팩토리 메서드의 장점
- 더 명확한 이름 제공: 메서드 이름을 통해 객체 생성의 의도나 특성을 명확히 전달할 수 있다.
public class User {
private String name;
private int age;
private User(String name, int age) {
this.name = name;
this.age = age;
}
public static User createAdult(String name) {
return new User(name, 20);
}
public static User createChild(String name) {
return new User(name, 12);
}
}
// 사용
User adult = User.createAdult("어른1");
User child = User.createChild("어린이1");
- 객체 재사용 및 캐싱: 같은 객체를 재사용하거나 캐싱하여 메모리 사용을 최적화할 수 있다.
public class BooleanCache {
private static final Boolean TRUE = new Boolean(true);
private static final Boolean FALSE = new Boolean(false);
public static Boolean valueOf(boolean value) {
return value ? TRUE : FALSE; // 캐싱된 객체 반환
}
}
// 사용
Boolean t1 = BooleanCache.valueOf(true);
Boolean t2 = BooleanCache.valueOf(true);
System.out.println(t1 == t2); // true
- 유연한 반환 타입: 생성자는 호출된 클래스의 객체만 반환하지만, 정적 팩토리 메서드는 하위 클래스나 관련 클래스의 객체도 반환 가능하다. 또한 인터페이스를 사용할 수 있어 더 유연한 설계를 가능하게 한다.
interface Shape {
void draw();
}
class Circle implements Shape {
public void draw() {
System.out.println("Drawing a Circle");
}
}
class Rectangle implements Shape {
public void draw() {
System.out.println("Drawing a Rectangle");
}
}
public class ShapeFactory {
public static Shape getShape(String type) {
if ("circle".equals(type)) {
return new Circle();
} else if ("rectangle".equals(type)) {
return new Rectangle();
} else {
throw new IllegalArgumentException("Unknown type: " + type);
}
}
}
// 사용
public class Main {
public static void main(String[] args) {
Shape circle = ShapeFactory.getShape("circle");
circle.draw(); // Drawing a Circle
Shape rectangle = ShapeFactory.getShape("rectangle");
rectangle.draw(); // Drawing a Rectangle
// 잘못된 입력 처리
try {
Shape unknown = ShapeFactory.getShape("triangle");
} catch (IllegalArgumentException e) {
System.out.println(e.getMessage()); // Unknown type: triangle
}
}
}
- 호출될 때마다 새로운 인스턴스를 생성하지 않아도 됨: 필요에 따라 새로운 객체를 생성하거나 기존 객체를 재사용할 수 있다.
public class ExpensiveObject {
private static final ExpensiveObject INSTANCE = new ExpensiveObject();
private ExpensiveObject() {
// 비싼 초기화 작업
}
public static ExpensiveObject getInstance() {
return INSTANCE; // 동일한 객체 재사용
}
}
// 사용
ExpensiveObject obj1 = ExpensiveObject.getInstance();
ExpensiveObject obj2 = ExpensiveObject.getInstance();
System.out.println(obj1 == obj2); // true
2. 생성자와 정적 팩토리 메서드 비교
비교 항목 | 정적 팩토리 메서드 | 생성자 |
메서드 이름 | 명확한 이름으로 생성 목적 전달 가능 | 클래스명과 동일해야 함 |
객체 재사용 | 캐싱 등을 통해 동일 객체 재사용 가능 | 항상 새로운 객체 생성 |
반환 타입 | 하위 클래스나 다른 타입 반환 가능 | 호출된 클래스의 인스턴스 반환 |
사용 편의성 | 가독성 높음 | 단순한 객체 생성에 적합 |
3. 정적 팩토리 메서드의 일반적인 명명 방식
- from: 입력 매개변수를 하나 받아 객체 생성
예: Date.from(instant) - of: 여러 매개변수를 받아 객체 생성
예: Set.of("A", "B") - valueOf: 변환 또는 매핑을 통해 객체 생성
예: Integer.valueOf("123") - instance / getInstance: 인스턴스를 반환
예: Calendar.getInstance() - create / newInstance: 새로운 객체 생성
예: Class.newInstance()
4. 주요 사용 예시
1. Boolean 클래스
불필요한 객체 생성을 방지하기 위해 캐싱을 활용
public class BooleanExample {
public static void main(String[] args) {
Boolean trueValue1 = Boolean.valueOf(true); // 기존 캐싱된 객체 반환
Boolean trueValue2 = Boolean.valueOf(true); // 동일한 객체 반환
System.out.println(trueValue1 == trueValue2); // true (같은 객체를 참조)
}
}
2. LocalDate 클래스
날짜와 관련된 객체를 명확하고 직관적으로 생성할 수 있다.
import java.time.LocalDate;
public class LocalDateExample {
public static void main(String[] args) {
LocalDate date = LocalDate.of(2024, 12, 10); // 특정 날짜 생성
System.out.println(date); // 2024-12-10
}
}
3. EnumSet 클래스
Enum의 집합을 생성할 때 사용한다.
import java.util.EnumSet;
enum Days {
MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY
}
public class EnumSetExample {
public static void main(String[] args) {
EnumSet<Days> weekend = EnumSet.of(Days.SATURDAY, Days.SUNDAY); // 특정 값 포함
System.out.println(weekend); // [SATURDAY, SUNDAY]
}
}
4. Collections 클래스
컬렉션 객체를 반환할 때 정적 팩토리 메서드를 활용
import java.util.Collections;
import java.util.List;
public class CollectionsExample {
public static void main(String[] args) {
List<String> emptyList = Collections.emptyList(); // 빈 리스트 반환
System.out.println(emptyList); // []
}
}
5. BigDecimal 클래스
정확한 숫자 연산을 위해 객체를 생성
import java.math.BigDecimal;
public class BigDecimalExample {
public static void main(String[] args) {
BigDecimal value = BigDecimal.valueOf(12345.6789); // 숫자를 BigDecimal로 변환
System.out.println(value); // 12345.6789
}
}
6. 사용자 정의 정적 팩토리 메서드
사용자 정의 클래스를 만들어 정적 팩토리 메서드를 구현할 수도 있다.
public class Person {
private String name;
private int age;
// private 생성자
private Person(String name, int age) {
this.name = name;
this.age = age;
}
// 정적 팩토리 메서드
public static Person of(String name, int age) {
return new Person(name, age);
}
@Override
public String toString() {
return "Person{name='" + name + "', age=" + age + "}";
}
public static void main(String[] args) {
Person person = Person.of("Alice", 25); // 정적 팩토리 메서드를 통해 생성
System.out.println(person); // Person{name='Alice', age=25}
}
}
728x90
반응형
'Programming Language > Java' 카테고리의 다른 글
[Java/개념] Optional<T> 클래스 (0) | 2024.12.05 |
---|---|
[Java/개념] Java 예외 처리(Exception Handling) (1) | 2024.12.05 |
[Java/개념] Math, Random (0) | 2024.12.05 |
[Java/개념] API)String, StringTokenizer, StringBuffer, StringBuilder (0) | 2024.12.05 |
[Java/개념] API 도큐먼트, java.lang, java.util, java.lang.Object, java.util.Object (0) | 2024.12.05 |