본문 바로가기
디자인패턴

팩토리 메서드 패턴 (Factory Method Pattern)

by 이석준석이 2021. 5. 29.

사용의도

  • 객체생성의 인터페이스를 제공하며, 객체의 생성은 서브클래스가 수행하도록 합니다.

장점

  • 객체 생성에 관련된 코드와 동작 코드를 분리할 수 있습니다.

구조


예시) 전사 / 마법사 캐릭터 생성

 

  전사 마법사
시작 체력 및 마력 100 / 100
레벨업 시 증가하는 체력 마력 20 / 10 10 / 20

 

차이점

  • 레벨업 시 증가하는 체력 마력이 다른 두개의 직업이 있습니다.
  • 추후에 두 직업간의 차이가 계속 생길 것을 대비하여, 다른 클래스를 통해 두개의 클래스를 생성합니다.
    • 이러한 과정에서 신규캐릭터를 인스턴스화 하는 경우, 팩토리 메서드 패턴을 사용하여 이를 구성해보겠습니다.

구조

GOF 설명 our class
Creator 추상클래스이며 구체클래스의 부모클래스로,
Product 타입을 반환하는 팩토리메소드 (abstract method) 를 갖고있습니다.
MyCharacterCreator
ConcreteCreator 팩토리메서드를 재정의하여 구체 클래스(ConcreteProduct) 를 리턴합니다. MagicianCreator
WarriorCreator
Product 팩토리메소드가 리턴하는 클래스의 추상클래스입니다. MyCharacter
ConcreteProduct Product 클래스에 정의된 메소드가 구현된 구체 클래스입니다. Magician
Warrior

MyCharacterCreatorMagicianCreator / WarriorCreator 간의 관계

  • 상속관계

MyCharacterMagician / Warrior 간의 관계

  • 상속관계

MagicianCreatorMagician 간의 관계

  • 인스턴스화 관계 : MegicianCreator 는 Magician 객체를 인스턴스화합니다.

WarriorCreatorWarrior 간의 관계

  • 인스턴스화 관계

위의 구조를 통해서, 팩토리메서드 패턴을 통해 클래스관계를 구성해보도록 하겠습니다.

 

먼저 팩토리메서드의 추상클래스인 MyCharacterCreator 입니다.

  • createNewCharacter()
    • public 으로 하여 외부에 공개하며
    • 공통코드 (체력100, 마력 100) 를 모아놓습니다.
  • createCharacter()
    • 자식클래스에서 구체클래스를 생성하게 합니다.
public abstract class MyCharacterCreator {

    public MyCharacter createNewCharacter() {
        final MyCharacter character = createCharacter(); <-- 이 부분에서 factory 메소드가 사용됨

        character.setHp(100);
        character.setMp(100);

        return character;
    }
    
    // Factory Method
    protected abstract MyCharacter createCharacter();
}
public class WarriorCreator extends MyCharacterCreator {
    @Override
    protected MyCharacter createCharacter() {
        return new Warrior();
    }
}
public class MagicianCreator extends MyCharacterCreator {
    @Override
    protected MyCharacter createCharacter() {
        return new Magician();
    }
}

@Getter
@Setter
public abstract class MyCharacter {

    protected int hp;
    protected int mp;

    public abstract void levelUp();
}

 

public class Warrior extends MyCharacter {
    @Override
    public void levelUp() {
        this.mp += 10;
        this.hp += 20;
    }
}
public class Magician extends MyCharacter {
    @Override
    public void levelUp() {
        this.hp += 10;
        this.mp += 20;
    }
}

 

호출하는 부분에서는 아래와 같이 사용할 있습니다.

// 마법사를 생성할 때
public static void main(String[] args) {
    final MagicianCreator magicianCreator = new MagicianCreator();

    final MyCharacter character = magicianCreator.createNewCharacter();

    character.levelUp();
}

// 전사를 생성할 때
public static void main(String[] args) {
    final WarriorCreator warriorCreator = new WarriorCreator();

    final MyCharacter character = warriorCreator.createNewCharacter();

    character.levelUp();
}