본문 바로가기
Programming/JAVA

[Effective Java] 생성자 대신 Static Factory Method를 사용하자

by 코딩의성지 2023. 1. 27.

아래 내용은 Effective Java를 읽고 내용을 정리한 것입니다 :) 

 

보통 개발자가 클래스의 인스턴스를 얻기 위해서 생성자를 사용한다. 허나 객체지향 개발자라면 Static Factory Mehtod를 이용하여 인스턴스를 얻는 방법도 알아두어야 한다.

 

아래 Laptop 클래스를 보자.

public class Laptop {
    private String model;
    private String company;

    public Laptop(String model, String company) {
        this.model = model;
        this.company = company;
    }

}

public 생성자의 아주 간단한 예를 살펴볼 수 있다.

 

보통 of 나 from 같은 정적 팩토리 메서드를 만들어 아래처럼 대체할 수 있다.

of 나 from을 언제 쓰느냐의 차이는 받는 파라미터로 생성될 객체를 판단할 수 있으면 of를 아니면 from을 보통 사용한다고 한다.  

public class Laptop {
    private String model;
    private String company;

    public static Laptop ofModelNameAndCompany(String model, String company) {
        Laptop laptop = new Laptop();
        laptop.company = company;
        laptop.model = model;
        return laptop;
    }

}

굳이 이렇게 정적 팩토리 메서드를 만들어 사용해야하나 하는 의문이 들 수 도 있다.  하지만 다양한 기업의 실무코드를 보면 이러한 정적팩토리 메서드가 많이 사용되고 있는것을 보실수 있다.

 

Effective java에서는 정적 팩터리 메서드가 생성자에 비해 5가지 장점이 있다고 언급하고 있다.

 

1. 이름을 가질 수 있다.

2. 호출될때마다 인스턴스를 새로 생성하지 않아도 된다.

3. 반환타입의 하위 타입 객체를 반환할 수 있는 능력이 있다.

4. 입력 매개변수에 따라 다른 클래스의 객체를 반환할 수 있다.

5. 정적 팩터리 메서드를 작성하는 시점에는 반환할 객체의 클래스가 존재하지 않아도 된다.

 

이렇게 장점도 많지만 단점도 몇개 있는데 먼저 Static Factory Method만 제공하게 되면 생성자가 없을수도 있어 상속받은 Class를 만들수 없다는 단점이 있고, 개발자가 해당 메서드의 기능을 잘 인지하지 못할 수도 있다는 단점이 있다. 하지만 정적 팩터리 메서드는 이러한 단점을 상쇄시킬 수 있는 큰 효과를 실무의 여러 상황에서 발휘한다.

 

Spring 기반의 RESTFul API를 만들어 본 사람들은 아래와 같은 코드가 익숙할 것이다.

public class MemberForm {
    private String name;
    private String email;
    
    //Getter & Setter
}
@PostMapping(value = "/join")
public MemberDTO joinMember(@RequestBody MemberForm memberForm) {
	// ... 회원 가입 로직 구현 ...//
}

예제에서는 Request 데이터는 Form 객체로 Response 데이터는 DTO객체로 설정해 두었는데, 이러한 과정에서 우리는 Form 객체를 Entity 객체로 , Entity 객체를 DTO 객체로 변환해주는 작업이 일부 필요하다. 이러한 작업을 반복적으로 수행하면 재사용성이 떨어지고,  비효율적인 코드가 늘어나는 문제가 생긴다.

 

이를 효율적으로 해결할 수 있는 방법이 바로 정적 팩토리 메서드 이다. 아래의 예시를 보자.

public class Member {
    private Long id;
    private String name;
    private String email;

    // getter & setter ...

    public static Member from(MemberForm memberForm) {
        Member member = new Member();
        member.name = memberForm.getName();
        member.email = memberForm.getEmail();
        return member;
    }
}

이렇게 해두면 실제로 변환하는 로직이 필요한 곳에서

 

Member.from(memberForm)

 

이런식으로 호출만 해주면 Entity 객체를 만들어 낼 수 있다.

마찬가지로 Dto 객체에서도 Entity를 받아서 Dto로 변환해주는 정적 팩토리 메서드를 만들어 주면 효율적인 활용이 가능하다.

 

public class MemberDTO {
    private String name;
    private String email;

    public static MemberDTO from(Member member) {
        MemberDTO memberDTO = new MemberDTO();
        memberDTO.name = member.getName();
        memberDTO.email = member.getEmail();

        return memberDTO;
    }
}

 

Ref.

조슈아 블로크, 『이펙티브 자바』, 프로그래밍인사이트(2020), p8-p13

반응형

댓글