2 분 소요

정적 팩토리 메서드

  • 자바 기초에서 객체를 생성하기 위해서 new라는 연산자를 사용하였다.
  • 단순히 [new + 생성할 객체의 클래스] 형식으로 작성하였다
  • 이와 달리 new 바로 사용하는 것이 아닌 하나의 메서드를 사용하여 객체를 생성하도록 만드는 형식을 정적 팩토리 매서드 라고 한다.

정적 팩토리 메서드를 쓰는 이유

  • 생성자 사용보다 정적 팩토리 매서드가 좋은 이유는 여러가지가 있다.

1. 메서드 이름을 통한 기능파악이 쉽다.

- Book이라는 도서를 나타내는 클래스가 있다고 해보자
- new Book(10000)라는 코드를 통해 객체를 생성한다고 하면 모르는 사람이 봤을 때, 10000이라는 매개변수로 도대체 어떤 객체를 만든다는 것이지 확실하지 않다. 이를 알려면 Book 클래스의 소스 코드를 봐야만 한다.
```java
public class Book{
  private int index

  private Book(int index){
    this.index=index
  }

  static Book indexOf(int index){
    return new Book(index)
  }
}
```
- 만약 Book 클래스에 다음과 같이 Book 객체를 반환하는 "indexOf"라는 static 매서드가 있다면 외부에서 indexOf라는 메서드 이름만으로 "index가 10000인 책의 객체를 생성한다"라고 한눈에 파악할 수 있다.
- 다른 추가적인 기능없이 문자 자체로서 의미를 가지게 하기에 효율적인 코딩이 가능해지는 것

2. 메모리를 덜 잡아먹는다.

- 객체를 생성한다는 것은 메모리 상의 공간을 하나 사용한다는 것.
- 생성자를 통해 객체를 생성하면 동일한 내용의 객체더라도 매번 공간이 하나씩 부여될 것이다.
- 정적 메서드는 이러한 중복을 줄여준다는 장점이 있다.

```java
  class WoodSword{
      private static WoodSword woodSword = null;

      private WoodSword(){}

      static WoodSword getDefaultWeapon(){
        if(woodSword==null){
          woodSword=new WoodSword;
        }
        return woodSword;
      }
  }
  ---------------------------------------------------
  public static void main(String[] args){
    WoodSword w1 = WoodSword.getDefaultWeapon;
    WoodSword w2 = WoodSword.getDefaultWeapon;
    System.out.println(w1==w2);//true

  }
```
- 게임에서 초보자에게 제공하는 기본 나무검을 모든 사용자마다 하나씩 객체를 만들게 허용하면 그만큼 메모리가 과부화될 것이다.
- 나무검이 스탯 변화가 불가능하다고 가정하면, 사용자가 나무검을 사용할 때 기존에 있는 나무검의 정보만 가져오게하여 기존 나무검 객체를 활용할 수 있게 만들 수 있다.
- 이렇게 자주 사용되는 객체를 재활용할 수 있다는 점에서 정적 메서드가 의미가 있다.

3. 매개변수에 따라 다른 결과를 반환할 수 있다.

- 자바의 다형성을 이용한 장점이다.
- 배달앱에서 중국집 거래 서비스를 만든다고 가정하자.
- 가격대 별로 서비스가 업그레이드 되고 이를 자동으로 주문에 반영하고자 한다.

``` java
@Getter
class Delivery{
  private String 목적지;
  private List<Food> foods;
  private Stirng 서비스;

  private Delivery delivery(String 목적지, String 음식){
    this.목적지=목적지;
    this.음식=음식;
  }

    static Delivery deliverWithService(String 목적지, List<Food> foods){
      int sumPrice = foods.steam().map(Food::get가격()).sum();
      if(sumPrice>=100000){
        return 서비스= 탕수육;
      }
      if(sumPrice>=30000){
        return 서비스= 군만두;
      }
      else 서비스= 단무지;
    }
  }
  !----------------------------------------------------!
  public static void main(String[] args){
    Delivery delivery1= deliverWithService(목적지1, 1번주음식들);
    Delivery delivery2= deliverWithService(목적지2, 2번주음식들);

  }
```
- 고객은 목적지와 음식 리스트만 입력하면 가격에 따라서 서비스가 알아서 결정되고 해당 주문이 가게에 전달 될 수 있게 된다.

4. 구현체를 숨길 수 있다.

- 만화영화 스폰지밥에선 플랑크톤이 게살버거 레시피를 훔치려고 하지만 번번히 실패한다. 이를 정적 메서드를 이용해 한번 예시로 구현해보자

```java
  public class 햄버거{
    private String bread;
    private String patty;
    private String source;

    private 햄버거(String bread, String patty, String source){
        this.bread=bread;
        this.patty=patty;
        this.source=source;
    }

    public static 햄버거 게살버거만들기(주문 햄버거){
        if(햄버거.getName() == 게살버거){
          return new 게살버거(getSecret_Bread(), getSecret_Patty(), getSecret_Source());
        }

    }
  }

```    
- 위의 햄버거 클래스에는 게살버거만들기 메서드가 정의되어있다.
- 만약 햄버거 주문이 들어왔는데 햄버거 이름이 게살버거하면?? 게살버거의 재료를 가져와 만들면 된다. 하지만 외부에서, 심자어 만드는 사람조차(메서드 호출자) 이를 감추게하고자 매개변수에 전부 매서드를 통해 값을 집어 넣었다.
- 즉 누구나 게살버거 만들기 메서드로 게살버거를 만들 수는 있지만 어떤 비밀 재료가 들어가는지는 알 수가 없게 된다.

정적 팩토리 메서드의 단점

  • 여러 장점이 있지만 단점 또한 존재 한다.
  • 정적 팩토리 메서드를 정의한 클래스의 변수들이 private로 선언되다 보니 확장에 제한이 생긴다.
  • 때문에 클래스간의 상속을 통한 유연한 구조 설계가 불가능해 진다.
  • 이러한 폐쇠성을 활용해 확장이 불가능, 즉 상속을 의도적으로 제한하는 클래스를 만들 때 정적 팩토리 메서드가 사용되기도 한다.

댓글남기기