인스턴스 생성
- 자바에서 객체를 생성하는 기본적인 방법은 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 |
댓글