---
description: 1.1.2 팩토리 패턴
---

# 1.1.2 Factory Pattern

팩토리 패턴(Factory Pattern)은 객체 생성의 로직을 캡슐화하여 코드에서 객체 생성 부분을 떼어내는 디자인 패턴입니다. 상속 관계에 있는 두 클래스에서 상위 클래스가 중요한 패턴을 결정하고, 하위 클래스에서 객체 생성을 구체화하는 내용을 결정합니다. 이를 통해 객체 생성 방식을 유연하게 변경할 수 있습니다.



**팩토리 패턴의 특징**

1. **객체 생성 캡슐화**: 객체 생성의 구체적인 내용을 감추고, 상위 클래스가 객체 생성의 기본 구조를 제공하며 하위 클래스가 이를 구체화합니다.
2. **유연한 설계**: 객체 생성 방식을 변경해도 코드의 다른 부분에 영향을 주지 않으므로, 코드를 유연하게 설계할 수 있습니다.



**팩토리 패턴 구현 예제 (Java)**

다음은 Java에서 팩토리 패턴을 구현한 예제입니다:

```java
// CoffeeType 열거형 정의
enum CoffeeType {
    LATTE, ESPRESSO
}

// 추상 클래스 Coffee
abstract class Coffee {
    protected String name;

    public String getName() {
        return name;
    }
}

// Latte 클래스 정의
class Latte extends Coffee {
    public Latte() {
        name = "Latte";
    }
}

// Espresso 클래스 정의
class Espresso extends Coffee {
    public Espresso() {
        name = "Espresso";
    }
}

// CoffeeFactory 클래스 정의
class CoffeeFactory {
    public static Coffee createCoffee(CoffeeType type) {
        switch (type) {
            case LATTE:
                return new Latte();
            case ESPRESSO:
                return new Espresso();
            default:
                throw new IllegalArgumentException("Invalid coffee type: " + type);
        }
    }
}

// Main 클래스 정의
public class FactoryPatternDemo {
    public static void main(String[] args) {
        Coffee coffee1 = CoffeeFactory.createCoffee(CoffeeType.LATTE);
        Coffee coffee2 = CoffeeFactory.createCoffee(CoffeeType.ESPRESSO);

        System.out.println("First coffee: " + coffee1.getName());  // Latte
        System.out.println("Second coffee: " + coffee2.getName()); // Espresso
    }
}
```

위 예제에서는 `CoffeeFactory` 클래스가 `createCoffee` 메서드를 통해 다양한 타입의 커피 객체를 생성합니다. `Latte`와 `Espresso` 클래스는 `Coffee` 클래스를 상속받아 구현되며, `createCoffee` 메서드는 `CoffeeType` 열거형을 기반으로 적절한 커피 객체를 반환합니다.



**팩토리 패턴의 장점과 단점**

**장점:**

* **객체 생성의 캡슐화**: 객체 생성 로직을 별도의 클래스로 분리하여 코드의 가독성과 유지 보수성을 높입니다.
* **유연성 향상**: 새로운 객체 타입이 추가되더라도 기존 코드를 크게 변경하지 않고 확장할 수 있습니다.
* **의존성 감소**: 클라이언트 코드가 구체적인 클래스에 의존하지 않으므로, 코드의 결합도가 낮아집니다.

**단점:**

* **코드 복잡성 증가**: 패턴을 구현하기 위해 추가적인 코드가 필요하므로, 코드의 복잡성이 증가할 수 있습니다.
* **객체 생성 지연**: 팩토리 메서드를 통해 객체를 생성하므로, 직접 객체를 생성하는 것보다 약간의 성능 저하가 발생할 수 있습니다.



팩토리 패턴은 객체 생성 로직을 캡슐화하여 코드의 유연성과 확장성을 높이는 데 유용한 패턴입니다. 다양한 객체 타입을 생성해야 하는 상황에서 특히 유용하며, 코드의 유지 보수성을 높이는 데 큰 도움을 줍니다.





### 팩토리 패턴 연습

```markdown
1. 팩토리 패턴 문제

문제: 팩토리 패턴을 사용하여 Shape 객체를 생성하는 ShapeFactory 클래스를 구현하세요. Shape 인터페이스는 draw() 메서드를 포함해야 하며, Circle와 Rectangle 클래스는 이를 구현해야 합니다. ShapeFactory 클래스는 주어진 문자열에 따라 적절한 Shape 객체를 반환해야 합니다.

요구사항:

Shape 인터페이스를 정의하고 draw() 메서드를 선언하세요.
Circle와 Rectangle 클래스는 Shape 인터페이스를 구현하세요.
ShapeFactory 클래스는 getShape(String shapeType) 메서드를 통해 Shape 객체를 생성하세요.
주어진 문자열이 "CIRCLE"이면 Circle 객체를, "RECTANGLE"이면 Rectangle 객체를 반환합니다.
힌트:

팩토리 패턴의 기본 구조를 참고하세요.
조건문을 사용하여 문자열에 따라 객체를 생성하세요.
출력 예시:

Drawing a circle
Drawing a rectangle
```

```java
public interface Shape {
    void draw();
}
```

```java
@Slf4j
@Component
public class Circle implements Shape {
    @Override
    public void draw() {
        log.info("Drawing a circle");
    }
}

@Slf4j
@Component
public class Rectangle implements Shape {
    @Override
    public void draw() {
        log.info("Drawing a rectangle");
    }
}
```

```java
@Component
public class ShapeFactory {

    @Autowired
    private Circle circle;

    @Autowired
    private Rectangle rectangle;

    public Shape getShape(String shapeType) {
        if (shapeType == null) {
            return null;
        }
        if (shapeType.equalsIgnoreCase("CIRCLE")) {
            return circle;
        } else if (shapeType.equalsIgnoreCase("RECTANGLE")) {
            return rectangle;
        }
        return null;
    }
}
```

```java
@RestController
public class ShapeController {

    @Autowired
    private ShapeFactory shapeFactory;

    @GetMapping("/shape/{type}")
    public String getShape(@PathVariable String type) {
        Shape shape = shapeFactory.getShape(type.toUpperCase());
        if (shape != null) {
            shape.draw();
            return "Drawing " + type.toLowerCase();
        } else {
            return "Invalid shape type: " + type;
        }
    }
}
```

```markdown
프로젝트 구조
src/main/java
    └── com/example/shapefactory
        ├── controller
        │   └── ShapeController.java
        ├── service
        │   ├── Shape.java
        │   ├── Circle.java
        │   ├── Rectangle.java
        │   └── ShapeFactory.java
        └── ShapeFactoryApplication.java
pom.xml
```
