Effective Java 아이템 1 - 생성자 대신 정적 팩토리 메서드를 고려하라

MinJee Lee·2022년 7월 14일
0

Effective Java

목록 보기
1/1
post-thumbnail

인스턴스를 생성할 때 클라이언트는 public 생성자 대신 정적 팩도리 메소드를 제공할 수 있다.

정적 팩토리 메소드

정적 팩토리란, 클래스의 인스턴스를 반환하는 단순한 정적 메서드 이다.

boolean 기본타입 박싱 클래스인 Boolean에서 발췌한 코드로 기본타입 boolean값을 받아 Boolean 객체 참조로 변환해 준다.

장점

1. 이름을 가질 수 있다.

생성자는 클래스 이름과 동일하게 함수 이름을 작성해야 한다는 규칙이 있다. 그래서 매개변수와 생성자 이름만으로 반환될 객체의 특성을 제대로 설명하지 못한다는 특징이 있다.

또한 타입의 순서와 갯수가 같은 동일 생성자를 만들수 없다. 자바에서 오버로딩을 지원하고 있지만

어디까지나 매개변수 타입의 순서와 갯수가 같아야 한다. 주석으로 표시한 코드가 그 예시이다.

정적 팩토리 메소드는 메소드 이름을 통해 객제의 특징을 나타낼 수 있다.

또한 하나의 시그니처로는 생성자를 하나만 만들 수 있는 것에 반해 정적 팩토리 메소드는

하나의 시그니처로도 여러 메소드를 만들 수 있다.

import java.util.*;

public class Order {

    private boolean prime;

    private boolean urgent;

    private Product product;

    private OrderStatus orderStatus;

	//	public Order(Product product, boolean prime) {
	//		this. prodect = prodect;
	//		this. prime = prime;
	//	}

	//	public Order(boolean Urgent, Product product) {
	//		this. prodect = prodect;
	//		this. urgent = urgent;
	//	}
	
	// 정적 팩토리 메서드
    public static Order primeOrder(Product product) {
        Order order = new Order();
        order.prime = true;
        order.product = product;
        return order;
    }
	// 정적 팩토리 메서드 
    public static Order urgentOrder(Product product) {
        Order order = new Order();
        order.urgent = true;
        order.product = product;
        return order;
    }

}

생성자는 클래스 이름 과 동일한 이름을 넣는다. 다만

위와 같이 생성자는 private으로 설정하고 static을 통해 객체를 생성할 수 있도록 하면 primeOrder이라는 이름을 가지게 되어 명시적인 선언이 가능하다.

2. 새로운 객체를 생성할 필요는 없다.

생성자는 이름 그대로 반드시 하나의 객체를 생성해야 한다.

그렇지만 정적 팩토리 메서드는 프로그래머가 임의로 작성한 메서드 이게 때문에 제약이 없다.

불변한 객체를 미리 만들어 놓고 그 객체를 재사용하는 식으로 코드를 작성할 수 있다.

객체가 불변함이 보장 된다면 굳이 하나의 객체를 생성해야 하는 생성자는 메모리 비용이 많이 드는 나쁜 선택이다.

    private boolean useAutoSteering;

    private boolean useABS;

    private Difficulty difficulty;

    private Settings() {}

    private static final Settings SETTINGS = new Settings();

    public static Settings getInstance() {
        return SETTINGS;
    } 

이렇게 객체 생성을 컨트롤 할 수 있어 인스턴스 통제 클래스라고 부르며, 어디까지 인스턴스를 살게 할 수 있을 지 결정할 수 있다.

싱글톤 패턴을 만들 때에도 유용하고 불변 클래스를 만들 때에도 사용된다.

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

상속 받은 자식 클래스의 객체를 반환할 수 있다는 뜻이다.

자식 클래스의 객체를 반환할 수 있게 해준다면 그 자식 클래스의 객체를 공개하지 않고 객체를 사용할 수 있다는 것이다.

명시한 인터페이스만 다른 시스템에 노출 시키고 구현체는 숨김으로써 객체지향 oop원칙을 잘 지키며 설계할 수 있다. 이를 인터페이스 기반 프레임워크라고 부른다.

다른 시스템에 노출시키려면 모두 public으로 제한자를 풀어야 되는데 구현체는 private로 숨기고 API 만 public 으로 만들고 그 인터페이스 정적 팩토리 메서드에서 구현체들을 반환만 해주는 것이다.

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

장점 3. 의 연장 선 개념이다. 조건에 따라 하위 타입의 객체를 반환할 수 있게 설계가 가능하다.

이 책에서는 EnumSet클래스를 예로 들며 이 클래스는 public 생성자가 없고 원소의 갯수에 따라 객체를 반환하는 메서드만 있다고 한다.

원소가 63개 이하면 Regular Intellij 에서 직접 확인 해 보았다.

맨 마지막 EnumSet 생성자를 보면 접근 제한자가 없다. 같은 패키지 내에서만 호출 될 수 있다.

그리고, noneOf라는 정적 팩토리 메서드에서 원소의 개수에 따라 하위클래스의 객체를 반환하는 것을 볼 수 있다.

이 클래스를 사용하는 프로그래머 입장에서는 저런 세세한 구현을 알지 못하더라도 공통적인 기능의 EnumSet을 사용할 수 있게 된다.

장점 3에서 이야기 하였듯이 실제 구현은 공개하지 않았는데도 명세서만 보고 개발이 가능하다.

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

단점

1. 상속이 불가능하다 == 하위 클래스를 만들지 못 한다.

2. 프로그래머가 정적 팩토리 메서드를 찾기 어렵다.

작성중...

0개의 댓글