inblog logo
|
parangdajavous
    Design pattern

    Design pattern 6. static factory method

    김미숙's avatar
    김미숙
    Jul 22, 2025
    Design pattern 6. static factory method
    Contents
    ✅ static factory method예제💡 Of 와 From 의 차이예제

    ✅ static factory method

    • 자바에서 객체를 생성하는 한 가지 방법으로, new 키워드를 직접 쓰지 않고, 정적 메서드를 통해 객체를 반환하는 방식
     

    ✅ 기본 예시

    public class User { private String name; private User(String name) { this.name = name; } // 정적 팩토리 메서드 public static User of(String name) { return new User(name); } }
    User user = User.of("홍길동"); // new User("홍길동") 대신 사용
     

    ✅ 장점 6가지 (Effective Java 3판 기준)

    1. 이름을 가질 수 있다 🏷️
    • 생성자보다 이름 있는 메서드가 더 의도를 잘 표현함
    BigInteger big1 = BigInteger.valueOf(1L); // 의미 명확 BigInteger big2 = new BigInteger("1"); // 상대적으로 불분명
     
    2. 호출 시마다 새 객체를 생성하지 않아도 된다 ♻️
    • 캐싱, 싱글턴, 불변 객체 등에 유용
    Boolean b = Boolean.valueOf(true); // 항상 동일 객체 반환 (true/false 재사용)
     
    3. 하위 타입을 반환할 수 있다 🔁
    • 반환 타입을 인터페이스로 숨기고, 실제 구현은 내부에서 결정 가능
    public static List<Integer> emptyList() { return Collections.emptyList(); // 실제로는 ImmutableEmptyList 반환 }
     
    4. 제네릭 타입 추론이 가능 💡
    Map<String, List<String>> map = Map.of(); // 타입 추론됨
     
    5. 인스턴스화 로직을 한 곳에 모을 수 있다
    • of(), from(), valueOf() 등 여러 이름으로 상황별 분기 가능
     
    6. 생성자를 감출 수 있다 🔒
    • 외부에서 new로 직접 생성 못하도록 제한
    • enum, 싱글턴, 도메인 객체 생성 등에서 유용
     

    ❌ 단점

    단점
    설명
    생성자처럼 상속이 불가능
    User.of()는 상속 구조에서 오버라이드 어려움
    정적 메서드는 이름으로만 구분
    오버로딩은 가능하지만 명확하지 않을 수 있음
    개발자들이 of()의 의미를 이해해야 함
    생성자보다 문서화가 중요함
     

    ✅ 자주 쓰는 네이밍 관례

    메서드 이름
    용도
    of()
    단순한 객체 생성
    from()
    변환
    valueOf()
    값 기반 생성
    getInstance()
    싱글턴 or 캐시
    newInstance()
    항상 새 객체 생성
    instance()
    싱글턴 반환 (요즘 잘 안 씀)
    ✅ 실제 예: Enum.valueOf()
    DayOfWeek day = DayOfWeek.valueOf("MONDAY");
     

    ✅ 요약

    특징
    설명
    메서드 기반 객체 생성
    생성자 대신 정적 메서드로 생성
    이름 부여 가능
    의도를 명확히 표현
    캐싱, 싱글턴 등 유연
    new보다 제어 쉬움
    하위 타입 반환 가능
    인터페이스와 함께 많이 사용

    예제

    User
    package ex96.type2; public class User { private Integer id; private String username; private String password; private String role; // Teacher, Student // 학생 private Integer score; private Integer level; // 선생 private Integer sal; private String position; public static User createStudent() { return new User(null, "ssar", "1234", "STUDENT", 100, 1, null, null); } public static User createTeacher() { return new User(null, "ssar", "1234", "TEACHER", null, null, 3000, "MANAGER"); } private User(Integer id, String username, String password, String role, Integer score, Integer level, Integer sal, String position) { this.id = id; this.username = username; this.password = password; this.role = role; this.score = score; this.level = level; this.sal = sal; this.position = position; } }
    App
    package ex96.type2; public class App { public static void main(String[] args) { User teacher = User.createTeacher(); User student = User.createStudent(); } }
     

    💡 Of 와 From 의 차이

    ✅ 차이 요약

    메서드 이름
    사용 목적
    예시
    의미
    of(...)
    직접 구성 요소로부터 객체 생성
    User.of(name, age)
    “이 필드들로부터 만든다”
    from(...)
    다른 타입/객체로부터 변환
    User.from(UserDTO dto)
    “변환해서 만든다”
     

    ✅ of(...)는 언제 쓰나?

    • 필드 값 자체를 받아 객체를 만들 때
    • 즉, 구성 요소들(primitive, enum, 값 객체 등)로 객체를 구성할 때
    • 보통 여러 매개변수가 있든 없든 직접 필드 값을 넘길 때
    예시
    public class Point { private final int x; private final int y; private Point(int x, int y) { this.x = x; this.y = y; } public static Point of(int x, int y) { return new Point(x, y); } }
    ✔️ 특징
    • 필드 하나만 있어도 쓸 수 있음 (매개변수 개수 상관 없음)
    public static Boolean of(boolean value) { return value ? TRUE : FALSE; }
     

    ✅ from(...)은 언제 쓰나?

    • 다른 객체 또는 형식을 변환할 때
    • 즉, 외부에서 들어온 DTO, JSON, API 응답 등에서 내부 도메인 객체로 바꿀 때
    예시
    public class User { private String name; private int age; public static User from(UserDTO dto) { return new User(dto.getName(), dto.getAge()); } }
    ✔️ 특징
    • 매개변수는 보통 1개 (변환 대상)
    • 변환의 의미를 명확히 함
     

    ✅ 보너스: valueOf(...)는?

    • 기존 값이나 문자열로부터 객체를 만들 때
    • 보통 기본 타입 → 객체로 바꿀 때 (Wrapper 클래스에서 자주 사용)
    Integer i = Integer.valueOf("123"); DayOfWeek day = DayOfWeek.valueOf("MONDAY");
     

    ✅ 실전 구분 팁

    상황
    메서드 이름 추천
    필드 값을 직접 넣어서 객체를 만들고 싶다
    of(...)
    DTO → Entity 변환하고 싶다
    from(dto)
    문자열, 숫자, enum 값 등으로 변환
    valueOf(...)
     

    ✅ 요약 문장

    • of(...)는 객체를 구성하는 값들로 객체를 만들 때
    • from(...)은 다른 객체로부터 변환할 때
    • valueOf(...)는 기본 값(String, int 등)으로부터 변환할 때
     

    예제

    Rectangle
    package ex96.type2; public class Rectangle { private double x; private double y; private double width; private Rectangle(double x, double y, double width) { this.x = x; this.y = y; this.width = width; } public static Rectangle from(String value) { if (value.equals("small")) { return new Rectangle(50, 50, 50 * 50); } else if (value.equals("medium")) { return new Rectangle(100, 100, 100 * 100); } else if (value.equals("large")) { return new Rectangle(200, 200, 200 * 200); } else { throw new IllegalArgumentException("Invalid rectangle value"); } } public static Rectangle of(double x, double y) { return new Rectangle(x, y, x * y); } }
    App
    package ex96.type2; public class App { public static void main(String[] args) { Rectangle smallR = Rectangle.from("small"); Rectangle mediumR = Rectangle.from("medium"); Rectangle largeR = Rectangle.from("large"); } }
    Share article
    Contents
    ✅ static factory method예제💡 Of 와 From 의 차이예제

    parangdajavous

    RSS·Powered by Inblog