Java

팩토리 메서드 패턴을 적용해보자

siwoli 2023. 10. 26. 15:52

팩토리 메서드 패턴이란?

  • 오버라이드된 메서드가 객체를 반환하는 패턴
  • 팩토리 메서드 : 객체를 생성함과 동시에 반환하는 메서드
  • 하위 클래스에서 팩토리 메서드를 오버라이딩해서 서로 다른 객체를 반환한다.
  • 하위 클래스에서 구체적인 객체 생성 방법을 결정한다.
  • 객체지향 설계 원칙 중 의존 역전 원칙(Dependency Inversion Principle)이 적용된 패턴이다.

템플릿 메서드 패턴과 비슷하면서도 다르다.
템플릿 메서드 패턴은 식품 공장 중 하나의 과자 공장에서 서로 다른 종류의 과자를 만드는 거라면
팩토리 메서드 패턴은 식품 공장 중 과자 종류별 공장들에서 각자의 과자를 만드는 거라고 볼 수 있다.

 

팩토리 메서드 패턴은 생성자를 반환해서 그 생성자만의 동작을 수행하도록 하는데 초점이 맞춰저 있다.
전체 구조에 영향을 최소화하고 객체를 어떻게 사용할지 정할 수 있다.

 

우테코 프리코스 1주차에서 게임을 실행하는 기능에 이를 적용했다.

먼저 공통된 메서드를 수행하도록 팩토리 인터페이스를 만들었다.

public interface GameFactory {
    Game create();
}

Game은 게임 단위별 클래스들의 상위 클래스로, 객체를 반환할때 공통된 타입을 지정하기 위해 만들었다.

그다음 각 게임 단위별 구현 클래스를 만들어 해당하는 게임단위의 객체를 반환하는 메서드를 만들었다.

public class UnitOfGameFactory implements GameFactory {
    @Override
    public UnitOfGame create() {
        return new UnitOfGame(new ComputerNumbersGenerator());
    }
}
public class SetOfGameFactory implements GameFactory {
    @Override
    public SetOfGame create() {
        return new SetOfGame(new UnitOfGameFactory());
    }
}

SetOfGame은 게임 한 세트를 실행한다.
생성자로 UnitOfGameFactory객체를 받아서 create()UnitOfGame객체를 받아 사용한다.

public class SetOfGame extends Game {

    private final UnitOfGameFactory unitOfGameFactory;

    public SetOfGame(UnitOfGameFactory unitOfGameFactory) {
        this.unitOfGameFactory = unitOfGameFactory;
    }

    @Override
    public void play() {
        String userInput;

        do {
            UnitOfGame unitOfGame = unitOfGameFactory.create();
            unitOfGame.play();
            userInput = promptUserInput();
        } while (Objects.equals(userInput, "1"));
    }

    private String promptUserInput() {
        String userInput;
        do {
            GameView.printAfterSetOfGame();
            userInput = readLine();
        } while (!Objects.equals(userInput, "1") && !Objects.equals(userInput, "2"));
        return userInput;
    }
}

TotalGameSetOfGameFactory객체를 받아서 create()를 통해 SetOfGame객체를 사용한다.

public class TotalGame extends Game{
    private final SetOfGameFactory setOfGameFactory;

    public TotalGame(SetOfGameFactory setOfGameFactory) {
        this.setOfGameFactory = setOfGameFactory;
    }
    @Override
    public void play() {
        GameView.printBeforeTotalGame();
        SetOfGame setOfGame = setOfGameFactory.create();
        setOfGame.play();
        GameView.printAfterTotalGame();
    }
}

이게 맞는 방법인지 확실하진 않지만 이렇게 하니 각 게임 단위별 클래스를 공통된 로직으로 다르게 사용할 수 있었다.