본문 바로가기
Study/CS

[CS] 디자인패턴 - 팩토리(if 없애기)

by dev_kong 2023. 1. 5.
728x90
728x90

 

디자인 패턴이란?
프로그램을 설계할 때 발생했던 문제점들을 해결 할 수 있도록 하나의 규약형태로 만들어 놓은 것.

 

팩토리패턴

 

팩토리 패턴이란?
객체를 사용하는 코드에서 객체 생성 부분을 떼어내 추상화한 패턴이다.
상위 클래스가 중요한 뼈대를 겨정하고, 하위 클래스가 객체생성에 관한 구체적인 내용을 결정하는 패턴.

 

Java 예시코드

 

라떼와, 아메리카노를 만들어내는 팩토리패턴을 구현해보려 한다.

우선 추상 클래스인 Coffee를 만들어 보자.

 

public abstract class Coffee {
    public abstract int getPrice();
    abstract String getName();

    @Override
    public String toString() {
        return String.format("%s 는 %d 원", getName(), getPrice());
    }
}

 

생성한 추상 클래스를 이용해 Americano클래스와 Latte클래스를 생성한다.

 

// Americano
public class Americano extends Coffee{

    private final int price;
    private final String name = "Americano";

    public Americano(int price) {
        this.price = price;
    }

    @Override
    public String getName() {
        return name;
    }

    @Override
    public int getPrice() {
        return 0;
    }
}

//Latte
public class Latte extends Coffee{
    private final int price;
    private final String name = "라떼";

    public Latte(int price) {
        this.price = price;
    }

    @Override
    public String getName() {
        return name;
    }

    @Override
    public int getPrice() {
        return price;
    }
}

 

이번엔 상위클래스가 될, CoffeFactory를 구현한다.

 

public class CoffeeFactory {
    public static Coffee getCoffee(String type, int price) {
        if ("Latte".equals(type)) {
            return new Latte(price);
        }

        if("Americano".equals(type)) {
            return new Americano(price);
        }

        throw new IllegalArgumentException("그딴 커피 없음");
    }
}

 

이렇게 하면 된다.

 

테스트

class CoffeeFactoryTest {

    @Test
    void 팩토리_테스트() {
        Coffee latte = CoffeeFactory.getCoffee("Latte", 1000);
        String result = latte.toString();
        String expect = "라떼 는 1000 원";

        assertThat(expect).isEqualTo(result);
    }
}

잘된다. 아주.

 

리팩토링

if 문이 꼴보기 싫다.
enummap을 이용해 매핑하여 condition 없이 만들 수 있다.
enum 좋아하니까 enum으로 리팩토링 해보려 한다.

 

// CoffeeEnum

public enum CoffeeEnum {
    LATTE_COFFEE("Latte") {
        public Coffee create(int price) {
            return new Latte(price);
        }
    },

    AMERICANO("Americano") {
        public Coffee create(int price) {
            return new Americano(price);
        }
    };

    private final String type;

    CoffeeEnum(String type) {
        this.type = type;
    }

    public Coffee create(int price) {
        return null;
    }

    public static Coffee createCoffeeByType(String type, int price) {
        CoffeeEnum coffeeEnum = findCoffeeByType(type);
        return coffeeEnum.create(price);
    }

    private static CoffeeEnum findCoffeeByType(String type) {
        return Stream.of(CoffeeEnum.values())
                .filter(coffeeEnum -> coffeeEnum.type.equals(type))
                .findFirst()
                .orElseThrow(() -> new IllegalArgumentException("그딴 커피 없습니다."));
    }
}

 

enum을 생성해주고,
CoffeeFactory를 리팩토링 해보자.

 

// CoffeeFactory

public class CoffeeFactory {
    public static Coffee getCoffee(String type, int price) {
        return CoffeeEnum.createCoffeeByType(type, price);
    }
}

 

훨씬 간결해졌다.

다시 테스트 돌려보면, 아주 잘된다.

728x90
728x90

댓글