본문 바로가기
Backend/Java

인스턴스 생성과 정적 팩토리 메서드

by unknownomad 2024. 3. 25.


인스턴스 생성

  • 자바에서 객체를 생성하는 기본적인 방법은 new 키워드를 사용하여 생성자를 호출하는 방식
  • 가장 직관적이고 간단한 방법

예시

public class Car {
    private String model;
    private int year;

    // 생성자
    public Car(String model, int year) {
        this.model = model;
        this.year = year;
    }

    public void displayInfo() {
        System.out.println("Model: " + model + ", Year: " + year);
    }
}

// 인스턴스 생성
public class Main {
    public static void main(String[] args) {
        Car myCar = new Car("Tesla Model 3", 2023);  // 기본 생성자 사용
        myCar.displayInfo();
    }
}

 

장점

  • 간단하고 직관적
  • 객체 생성 방법이 명시적이고 이해하기 쉬움

단점

  • 복잡한 로직을 포함하면 생성자가 비대해질 수 있음
  • 객체 생성 방식이 외부에 노출되어 관리와 유지보수가 어려워질 수 있음

정적 팩토리 메서드

  • 정적 팩토리 메서드는 객체 생성 로직을 클래스의 정적 메서드로 캡슐화하여 객체 생성 방식을 제어하는 방법
  • 이 방식은 객체 생성 방식에 유연성을 제공

예시

public class Car {
    private String model;
    private int year;

    // 생성자
    private Car(String model, int year) {  // 외부에서 호출되지 않도록 private으로 설정
        this.model = model;
        this.year = year;
    }

    // 정적 팩토리 메서드
    public static Car createTesla() {
        return new Car("Tesla Model S", 2023);
    }

    public static Car createBMW() {
        return new Car("BMW 320i", 2022);
    }

    public void displayInfo() {
        System.out.println("Model: " + model + ", Year: " + year);
    }
}

// 정적 팩토리 메서드를 이용한 인스턴스 생성
public class Main {
    public static void main(String[] args) {
        Car teslaCar = Car.createTesla();  // 정적 팩토리 메서드 사용
        teslaCar.displayInfo();

        Car bmwCar = Car.createBMW();  // 또 다른 정적 팩토리 메서드 사용
        bmwCar.displayInfo();
    }
}

 

장점

  • 객체 생성 로직을 캡슐화하여 외부에서 객체 생성 방법을 알 필요 없음
  • 다양한 객체 생성 방식을 지원(싱글턴, 캐싱 등)
  • 객체 생성 로직을 한 곳에서 관리하여 코드 재사용성 높임

단점

  • 코드가 직관적이지 않아서 이해가 어려울 수 있음
  • 객체 생성 방식이 은폐되어 디버깅이 어려울 수 있음

싱글턴 패턴

public class Singleton {
    private static Singleton instance;

    // 생성자는 private으로 설정하여 외부에서 객체 생성을 막음
    private Singleton() {}

    // 정적 팩토리 메서드: 객체를 최초 1회만 생성하고 이후 같은 객체를 반환
    public static Singleton getInstance() {
        if (instance == null) {
            instance = new Singleton();
        }
        return instance;
    }

    public void showMessage() {
        System.out.println("싱글턴 객체입니다.");
    }
}

public class Main {
    public static void main(String[] args) {
        Singleton obj1 = Singleton.getInstance();
        Singleton obj2 = Singleton.getInstance();

        // 두 객체는 동일한 인스턴스를 참조
        System.out.println(obj1 == obj2);  // true 출력
        obj1.showMessage();
    }
}
  • getInstance() 메서드는 최초 호출 시에만 객체를 생성하고, 이후에는 같은 인스턴스를 반환하여 싱글턴 패턴을 구현

 

캐싱

import java.util.HashMap;
import java.util.Map;

public class Car {
    private String model;

    // 생성자
    private Car(String model) {
        this.model = model;
    }

    public void showInfo() {
        System.out.println("Car model: " + model);
    }

    // 캐시 맵을 사용하여 객체를 재사용
    private static Map<String, Car> cache = new HashMap<>();

    // 정적 팩토리 메서드: 모델명이 같으면 캐시된 객체를 반환
    public static Car getCar(String model) {
        if (!cache.containsKey(model)) {
            cache.put(model, new Car(model));
        }
        return cache.get(model);
    }
}

public class Main {
    public static void main(String[] args) {
        Car car1 = Car.getCar("Tesla");
        Car car2 = Car.getCar("Tesla");

        // car1과 car2는 같은 객체를 참조
        System.out.println(car1 == car2);  // true 출력
        car1.showInfo();
    }
}

 

  • getCar() 메서드는 모델명이 동일한 객체를 캐시에서 찾아 반환하고, 새로운 객체는 한 번만 생성하여 캐시됨

정적 팩토리 메서드의 특징

생성 목적에 대한 이름 표현

  • 생성자의 이름은 항상 클래스 이름과 동일하지만, 정적 팩토리 메서드는 메서드 이름을 통해 객체 생성의 목적이나 의미를 명확히 표현할 수 있음
  • 예) createTesla(), createBMW()와 같이 메서드 이름만으로 객체의 종류나 목적을 알 수 있음

인스턴스 통제 관리

  • 정적 팩토리 메서드는 객체 생성 방식에 대해 더 많은 제어를 제공
  • 예) Singleton 패턴을 구현하여, 특정 클래스에 대한 인스턴스를 하나만 생성하고 이를 관리할 수 있음
  • 이는 객체 생성의 중복을 방지하고 메모리 낭비를 줄일 수 있음

하위 자료형 객체 반환

  • 정적 팩토리 메서드는 반환 타입을 유연하게 설정할 수 있음
  • 예) 구체적인 클래스 대신 인터페이스나 추상 클래스를 반환함으로써 코드의 유연성을 높이고, 의존성 역전 원칙(DIP)을 지킬 수 있음
  • 하위 자료형을 반환하는 방식으로 클라이언트 코드가 구체적인 구현을 알 필요 없이 추상화된 객체를 다룰 수 있음

인자에 따라 다른 객체 반환하도록 분기 가능

  • 정적 팩토리 메서드는 인자에 따라 다양한 객체를 반환할 수 있음
  • 예) 조건에 따라 서로 다른 종류의 객체를 반환하는 방식으로 객체 생성 로직을 더 유연하게 처리할 수 있음
  • 이는 객체 생성 로직에 대한 분기 처리를 메서드 내부에서 쉽게 구현할 수 있도록 도와줌

객체 생성 캡슐화

  • 객체 생성 로직을 정적 팩토리 메서드로 캡슐화하여, 외부에서는 어떻게 객체가 생성되는지 몰라도 상관없음
  • 이로 인해 객체의 생성과 초기화 과정을 변경하거나 최적화할 때, 외부 코드에 영향을 주지 않고 쉽게 수정할 수 있음

정적 팩토리 메서드의 문제점

직관적이지 않음

  • 생성자는 클래스 이름과 동일하지만, 정적 팩토리 메서드는 메서드 이름을 통해 목적을 알리기 때문에 처음 보는 사람에게는 이해하기 어려울 수 있음
  • 코드가 복잡해지면 메서드 이름만으로 객체 생성 방식을 완전히 이해하기 어려울 수 있음

디버깅 어려움

  • 객체 생성 방식이 메서드 안에 숨겨져 있기 때문에, 객체가 어떻게 생성되는지 추적하기 어려울 수 있음
  • 정적 팩토리 메서드가 많을 경우, 디버깅 시 객체가 어떤 방식으로 생성되는지에 대한 흐름을 파악하기 어려움

인스턴스화 제어 어려움

  • 정적 팩토리 메서드는 생성자 대신 사용되므로, 클래스의 생성 방식을 완전히 제어하기 어려운 경우가 발생할 수 있음
  • 예) 상속을 활용한 객체 생성 제어가 어려워질 수 있음

생성자 사용에 대한 제한

  • 클래스의 생성자가 private으로 설정되면, 외부에서 해당 클래스를 상속하거나 객체를 생성하는 데 제약이 있을 수 있음
  • 이로 인해 클래스의 유연성이 떨어질 수 있음

정리

  • 기본 생성자는 간단하고 직관적인 객체 생성 방법으로, 객체 생성 시 복잡한 로직이 필요하지 않은 경우 유용
  • 정적 팩토리 메서드는 객체 생성 방식을 제어하고, 생성 로직을 캡슐화할 수 있어 복잡한 객체 생성에 유리. 다양한 객체 생성 방식(싱글턴, 캐싱 등)을 구현할 수 있는 유연성을 제공
  • 문제점으로는 직관적이지 않고 디버깅이 어려울 수 있으며, 객체 생성 방식에 대한 제어가 제한될 수 있음

'Backend > Java' 카테고리의 다른 글

[인프런] 김영한의 자바 입문  (0) 2024.12.17
자바 리플렉션(Reflection)  (0) 2024.07.30
[Java] Annotation  (0) 2023.12.05
[Java] Exception  (0) 2023.12.05
[Java] Enum  (0) 2023.12.05

댓글