본문 바로가기

1.프로그래밍/Java

[Java] Factory Method Pattern 이란? (디자인 패턴, 간단한 예제)

728x90
반응형

[Java] Factory Method Pattern 이란? (디자인 패턴, 간단한 예제)

[Java] Singleton Pattern 이란? (디자인 패턴)

이전 글에서 Singleton Pattern에 대해 공부를 하고 글을 작성해 두었다.
위의 글에서 작성하였듯이 디자인 패턴은 크게 3가지로 분류되는데 생성패턴, 구조패턴, 행위패턴이다.


그 중 오늘 작성할 Factory Method Pattern은 생성패턴에 속한다.

Factory Method Pattern 이란?

팩토리 메서드 패턴(Factory method pattern)은 객체지향 디자인 패턴이다. Factory method는 부모(상위) 클래스에 알려지지 않은
구체 클래스를 생성하는 패턴이며.
자식(하위) 클래스가 어떤 객체를 생성할지를 결정하도록 하는 패턴이기도 하다.
부모(상위) 클래스 코드에 구체 클래스 이름을 감추기 위한 방법으로도 사용한다.


팩토리 메서드 패턴은 위와 같이 정의되어있다.
즉, 쉽게 말하자면 상위 클래스에서 정해지지 않은 하위 클래스 객체를 생성하여 주는 패턴이라고 이해하였다.


다른 글들을 찾아보면 하나같이 하는 말이 있다.
객체를 찍어내는 공장 같은 패턴이다 라는 말을 많이 보았다.
어느정도 꽤 잘 이해가 되는 문구이다.


하지만 이론만 이해한다고 되는것이 아니기에 코드를 직접 짜보자 했다.
구글에 여러가지 예제가 존재하지만 나에게 흥미가 더 있는걸로 간단한 예제를 직접 짜보기로했다.


운동을 좋아해 프로틴(유청 단백질) 클래스를 짜내는 팩토리 메서드 패턴을 구현하려고 했다.
이런놈도 있구나 하고 피식 웃으면서 봐주면 감사하겠다.

Code

Protein

public abstract class Protein {
    // 이름
    public abstract String getName();
    // 탄수화물
    public abstract int getCarboHydrate();
    // 단백질
    public abstract int getProtein();
    // 지방
    public abstract int getFat();

    public String toString(){
        return "name: " + getName() + " (oneServing) carboHydrate: " + getCarboHydrate() + " protein: " + getProtein() + " fat: " + getFat();
    }

}

MyProtein

public class MyProtein extends Protein {

    private String name;
    private int carboHydrate;
    private int protein;
    private int fat;

    public MyProtein(String name, int carbo, int protein, int fat){
        this.name = name;
        this.carboHydrate = carbo;
        this.protein = protein;
        this.fat = fat;
    }

    public String getName() {
        return name;
    }
    public int getCarboHydrate() {
        return carboHydrate;
    }
    public int getProtein() {
        return protein;
    }
    public int getFat() {
        return fat;
    }
}

Ns 와 Combat, Syntha 모두 동일
사실 공부를 하는 과정에서 코드를 짜면서, 하위 클래스의 객체변수 값들이 동일하기에 상위 클래스(Protein.class)에 작성하여 super() 메서드를 사용하고 싶었다.


하지만 많은 예제들이 위와 비슷한 형식으로 작성하였고,
작성하면서 다시한번 팩토리 메서드의 정의에 대해 생각하였다.


상위 클래스에서 정해지지 않은 하위 클래스 객체를 생성해주는 패턴이기 때문에,
하위 클래스의 인자값 혹은, 다른 데이터 값이 어떤것이 들어갈지 상정하지 않기에 저렇게 작성하는 것이 맞겠구나 생각하였고, 위와 같이 작성하였다.


Factory

public interface Factory {
    public Protein createProtein(String name, int carbo, int proteinRate, int fat);
}

ProteinFactory

public class ProteinFactory implements Factory {

    public Protein createProtein(String name, int carbo, int protein, int fat) {

        switch (name) {
            case "Myprotein":
                return new MyProtein(name, carbo, protein, fat);
            case "Ns":
                return new Ns(name, carbo, protein, fat);
            case "Combat":
                return new Combat(name, carbo, protein, fat);
            case "Syntha":
                return new Syntha(name, carbo, protein, fat);
            default:
                return null;
        }

    }
}

ProteinFactory에서는 이름을 이용해 switch문을 작성하여 각각의 생성자를 통해 객체를 생성하여 반환하게 구현하였다.


Main

public class Main {
    public static void main(String[] args) {

        ProteinFactory proteinFactory = new ProteinFactory();

        Protein protein1 = proteinFactory.createProtein("Myprotein", 2, 18, 2);
        Protein protein2 = proteinFactory.createProtein("Ns", 4, 23, 2);
        Protein protein3 = proteinFactory.createProtein("Combat", 3, 25, 2);
        Protein protein4 = proteinFactory.createProtein("Syntha", 15, 22, 6);

        System.out.println(protein1.toString());
        System.out.println(protein2.toString());
        System.out.println(protein3.toString());
        System.out.println(protein4.toString());

    }
}

/*
출력
name: Myprotein (oneServing) carboHydrate: 2 protein: 18 fat: 2
name: Ns (oneServing) carboHydrate: 4 protein: 23 fat: 2
name: Combat (oneServing) carboHydrate: 3 protein: 25 fat: 2
name: Syntha (oneServing) carboHydrate: 15 protein: 22 fat: 6
*/

위와 같이 객체 생성을 팩토리 클래스에 위임하여 각기 다른 하위 객체들을 생성하였다.
만약, 다른 하위 객체가 생성된다면 아마도 수정을 최소화 하여 그 객체또한 생성할 수 있을거라 생각된다.

728x90
반응형