기본 생성자가 아닌 static
메서드로 객체를 생성하고 리턴하는 패턴
public class Car {
private String model;
// 생성자
public Car(String model) {
this.model = model;
}
// 정적 팩토리 메서드
public static Car from(String model) {
return new Car(model);
}
}
1. 생성자 로직이 이름을 가질 수 있다.
Character
객체를 생성할 때 초보자와 마법사에 따라 생성하는 로직을 명시할 수 있다. 단순히 new
로 명명할 때 보다 가독성이 높아진다. 또한, 코드에서 볼 수 있듯이 생성자 로직은 private
으로 감싸 캡슐화를 유지한다.
public class Character {
...
// 생성자 감춘다.
private Character(String name, int health, int mana) {
...
}
// "초보자" 생성
public static Character createNovice(String name) {
return new Character(name, 50, 10);
}
// "마법사" 생성
public static Character createWizard(String name) {
return new Character(name, 80, 150);
}
}
2. 인스턴스 생성을 직접 관리/확장할 수 있다.
클래스에 대해 인스턴스를 생성하는데 완전한 주도권을 갖게된다. 그렇다면 미리 자주 쓰이며 불변인 객체를 만들어 두고 반환하면 될테다. 싱글톤과 캐싱의 개념이다.
미리 Settings
에 대한 불변 객체를 만들어 두고 생성자는 막고 정적 팩토리 메서드를 열어둔다. 그럼 다른 곳에서는 미리 생성되어 있는 객체만 반환된다. 캐싱에서도 활용할 수 있다.
Settings.java
public class Settings {
private String name;
private int settingCounts;
// 1. 유일한 인스턴스를 private static으로 미리 생성합니다.
private static final Settings INSTANCE = new Settings();
// 2. 생성자를 private으로 막습니다.
private Settings() {
this.name = "셋팅";
this.settingCounts = 0;
}
// 3. 정적 팩토리 메서드를 통해 항상 동일한 인스턴스를 반환합니다.
public static Settings getInstance() {
return INSTANCE;
}
}
Main.java
// SETTTINGS
Settings settings1 = Settings.getInstance();
Settings settings2 = Settings.getInstance();
System.out.println(settings1); // Settings@5c647e05
System.out.println(settings2); // Settings@5c647e05
3. 하위 타입을 반환한다.
인터페이스를 하나 두고 아래에 N개의 클래스를 둬서 해당 인터페이스를 반환하는 정적 팩토리 클래스/메서드를 둘 수 있다.
// 인터페이스
interface Shape {
void draw();
}
// 구현 클래스 1
class Circle implements Shape {
@Override
public void draw() {
System.out.println("원을 그립니다.");
}
}
// 구현 클래스 2
class Square implements Shape {
@Override
public void draw() {
System.out.println("사각형을 그립니다.");
}
}
// 팩토리 클래스
public class ShapeFactory {
// 반환 타입은 인터페이스인 Shape 입니다.
public static Shape createShape(String type) {
if ("circle".equalsIgnoreCase(type)) {
// 실제 반환되는 객체는 Circle 클래스의 인스턴스입니다.
return new Circle();
} else if ("square".equalsIgnoreCase(type)) {
// 실제 반환되는 객체는 Square 클래스의 인스턴스입니다.
return new Square();
}
throw new IllegalArgumentException("지원하지 않는 도형입니다.");
}
}