Java

정적 팩토리 메소드의 장점과 단점

yougeun 2024. 4. 6. 19:11
728x90

장점

1.메소드 이름이 있으므로 기본 생성자에 비해 가독성이 올라간다.

public class Character {
    int intelligence, strength, hitPoint, magicPoint;

    public Character(int intelligence, int strength, int hitPoint, int magicPoint) {
        this.intelligence = intelligence;   // 지능
        this.strength = strength;           // 힘
        this.hitPoint = hitPoint;           // HP
        this.magicPoint = magicPoint;       // MP
    }

    // 정적 팩토리 메소드
    public static Character newWarrior() {
        return new Character(5, 15, 20, 3);     // 전사는 힘과 HP가 높다
    }

    // 정적 팩토리 메소드
    public static Character newMage() {
        return new Character(15, 5, 10, 15);    // 마법사는 지능과 MP가 높다
    }
}

기본 생성자로 전사와 마법사의 새로운 캐릭터를 만드는 코드이다.

Character warrior = new Character(5, 15, 20, 3);
Character mage = new Character(15, 5, 10, 15);

기본 생성자로 캐릭터를 만들 경우 숫자들 가지고는 만드는 직업이 어떤 직업인지 알아보기 어렵다.

 

Character warrior = Character.newWarrior();
Character mage = Character.newMage();

정적 팩토리 메소드를 이용한다면 정적팩토리메소드의 이름을 통해 어떤 직업인지 정확히 구분가능하여 코드의 가독성이 올라가는 것을 볼 수 있다.

2.호출할 때마다 새로운 객체를 생성할 필요가 없다.

public class Singleton {
    private static Singleton singleton = null;

    private Singleton() {}

    public static Singleton getInstance(){
        if(singleton == null){
            singleton = new Singleton();
        }
        return singleton;
    }

}
public static void main(String[] args) {
        Singleton singleton1 = Singleton.getInstance();
        Singleton singleton2 = Singleton.getInstance();
        System.out.println(singleton1 == singleton2); // true
    }

불변클래스(Immutable class)는 인스턴스를 미리 만들거나,새로 생성한 인스턴스를 캐싱해서 재활용하기 때문에 불필요한 객체 생성을 줄일 수 있다.

생성자를 private로 제한해서 새로운 객체 생성을 제한하고 정적팩토리메소드인 getInstance()로 인스턴스를 생성하게 한다면 호출할때 마다 새로운 객체를 생성할 필요가 없어지게 된다.

 

3.하위 자료형 객체를 반환 할 수 있다.

public class Level {

    public static Level of(int score) {
        if (score < 50) {
            return new Basic();
        } else if (score < 80) {
            return new Intermediate();
        } else {
            return new Advanced();
        }
    }
    
}

public class Basic extends Level{}
public class Intermediate extends Level{}
public class Advanced extends Level{}

하위 자료형 객체를 반환하는 정적 팩토리 메서드의 특징은 상속을 사용할 때 확인할 수 있다. 이는 생성자의 역할을 하는 정적 팩토리 메서드가 반환값을 가지고 있기 때문에 가능한 특징이다.

시험 점수에 따라 결정되는하위 등급 타입을 반환하는 정적 팩토리 메서드를 만들면, 다음과 같이 분기처리를 통해 하위 타입의 객체를 반환할 수 있다.

 

4.객체 생성을 캡슐화 가능하다.

public class CarDto {
    private String name;
    private int position;

    public static CarDto from(Car car) {
        return new CarDto(car.getName(), car.getPosition());
    }
}
CarDto carDto = new CarDto(car.getName(), car.getPosition); // 생성자를 쓴 경우
Car carDto = CarDto.from(car); // 정적 팩토리 메서드를 쓴 경우

생성자를 사용하는 경우 외부에 생성자 내부 구현을 드러낸 채 사용한다 면정적 팩토리 메서드 패턴을 사용하면 내부 구현을 숨겨서 사용할 수 있다.

단점

1.상속에는 public 혹은 protected 생성자가 필요하므로 정적 팩토리 메소드만 제공할 경우 상속이 불가능하다.

2. 개발자가 임의로 만든 정적팩토리메소드와 기존의 정적메소드와 구분하기 어렵다.

개발자가 임의로 만든 정적팩토리메소드와 기존의 정적메소드를 쉽게 구분하기 위해 정적팩토리메소드는  네이밍 컨벤션이 존재한다.

네이밍 컨벤션

메서드
설명
예제
from
매개변수를 하나 받아 해당 타입의 인스턴스를 반환(형변환 method)
Date d = Date.from(instant);
of
여러 매개변수를 받아 적합한 타입의 인스턴스를 반환하는 집계 메서드
Set<Rank> faceCards = EnumSet.of(JACK, QUEEN, KING);
valueOf
fromof의 더 자세한 버전
BigInteger.valueOf(Integer.MAX_VALUE);
instance
getInstance
매개변수를 받을 경우 매개변수로 명시한 인스턴스를 반환하지만 같은 인스턴스임을 보장하지는 않음
StackWalker luke = StackWalker.getInstance(options);
create
newInstance
instance 혹은 getInstance와 같지만 매번 새로운 인스턴스를 생성해 반환한다.
Object newArr = Array.newInstance(classObj,arrayLen);
getType
getInstance와 같으나 생성할 클래스가 아닌 다른 클래스의 팩토리 메소드를 정의할 때 사용한다.
FileStore fs = Files.getFileStore(path)
newType
newInstance와 같으나 생성할 클래스가 아닌 다른 클래스의 팩토리 메소드를 정의할 때 사용한다.
BufferedReader br = Files.newBufferedReader(path);
type
getTypenewType의 간결한 버전
List<Complaint> litany = Collections.list(legachLitancy);

 

 

 

728x90