Menu
Coddy logo textTech

팩토리 패턴

Coddy Java 여정의 객체 지향 프로그래밍 섹션에 포함된 레슨 — 87개 중 66번째.

팩토리 패턴(Factory Pattern)은 객체 생성을 별도의 메서드나 클래스에 위임하는 생성 디자인 패턴입니다. 코드에서 new를 직접 사용하는 대신, 팩토리에 객체 생성을 요청합니다. 이는 공통 인터페이스나 부모 클래스를 공유하는 여러 관련 클래스가 있을 때 특히 유용합니다.

이메일, SMS 또는 푸시 알림을 보낼 수 있는 알림 시스템을 고려해 보세요. 팩토리가 없다면, 코드는 모든 구체 클래스에 대해 알고 있어야 합니다:

// 팩토리 없음 - 클라이언트는 모든 구체 클래스를 알아야 함
Notification notification;
if (type.equals("email")) {
    notification = new EmailNotification();
} else if (type.equals("sms")) {
    notification = new SMSNotification();
}

팩토리 패턴(Factory Pattern)을 사용하면 다음과 같이 생성 로직을 중앙 집중화할 수 있습니다:

public interface Notification {
    void send(String message);
}

public class EmailNotification implements Notification {
    public void send(String message) {
        System.out.println("Email: " + message);
    }
}

public class SMSNotification implements Notification {
    public void send(String message) {
        System.out.println("SMS: " + message);
    }
}

public class NotificationFactory {
    public static Notification create(String type) {
        if (type.equals("email")) {
            return new EmailNotification();
        } else if (type.equals("sms")) {
            return new SMSNotification();
        }
        return null;
    }
}

이제 클라이언트 코드는 더 깔끔해졌으며 구체적인 클래스에 의존하지 않습니다:

Notification notification = NotificationFactory.create("email");
notification.send("Hello!");  // 출력: Email: Hello!

주요 이점은 새로운 알림 유형을 추가할 때 팩토리만 업데이트하면 되며, 클라이언트 코드는 변경되지 않은 상태로 유지된다는 점입니다. 이는 인터페이스에 맞춰 프로그래밍한다는 원칙을 따르며, 시스템을 더 유연하고 확장하기 쉽게 만들어 줍니다.

challenge icon

챌린지

쉬움

팩토리 패턴(Factory Pattern)을 사용하여 도형 그리기 시스템을 만들어 봅시다! 코드 전체에서 직접 도형 객체를 생성하는 대신, 단순한 문자열 식별자를 기반으로 다양한 유형의 도형을 생성하는 팩토리에 생성 로직을 집중화할 것입니다.

코드는 다음 네 개의 파일로 구성됩니다:

  • Shape.java: 모든 도형의 공통 규약 역할을 하는 Shape라는 인터페이스를 정의합니다. 인터페이스에는 아무것도 반환하지 않지만 그려지는 도형에 대한 정보를 출력하는 단일 메서드 draw()를 선언해야 합니다.
  • Shapes.java: Shape 인터페이스를 구현하는 세 개의 클래스를 만듭니다:

    Circle - draw() 메서드는 "Drawing a Circle"을 출력해야 합니다.

    Rectangle - draw() 메서드는 "Drawing a Rectangle"을 출력해야 합니다.

    Triangle - draw() 메서드는 "Drawing a Triangle"을 출력해야 합니다.

  • ShapeFactory.java: 도형 생성을 처리하는 팩토리 클래스를 만듭니다. ShapeFactory에는 Shape를 반환하는 정적 메서드 createShape(String type)가 있어야 합니다. type 파라미터에 따라 다음과 같이 처리합니다:
    • type이 "circle"과 같으면, 새로운 Circle을 반환합니다.
    • type이 "rectangle"과 같으면, 새로운 Rectangle을 반환합니다.
    • type이 "triangle"과 같으면, 새로운 Triangle을 반환합니다.
    • 그 외의 값에 대해서는 null을 반환합니다.
  • Main.java: 팩토리 시스템을 하나로 묶습니다! 두 개의 입력(두 개의 도형 유형, 모두 String)을 받게 됩니다.

    각 입력에 대해 ShapeFactory를 사용하여 도형을 생성하고 Shape 변수에 저장합니다. 팩토리가 유효한 도형(null이 아님)을 반환하면 해당 도형의 draw() 메서드를 호출합니다. null을 반환하면 "Unknown shape: " 뒤에 제공된 입력 [type]을 붙여 출력합니다.

    두 입력을 순서대로 처리하며, 각각 별도의 줄에 출력합니다.

첫 번째 도형 유형(String)과 두 번째 도형 유형(String)의 두 가지 입력을 순서대로 받게 됩니다.

Main 클래스가 new Circle() 또는 new Rectangle()을 직접 사용하지 않는 점에 주목하세요. Main 클래스는 오직 Shape 인터페이스만 알고 있으며 팩토리에 객체 생성을 요청할 뿐입니다. 이것이 바로 팩토리 패턴의 힘입니다. 클라이언트 코드가 구체적인 클래스들로부터 분리(decoupled)되는 것입니다!

치트 시트

팩토리 패턴(Factory Pattern)은 객체 생성을 별도의 메서드나 클래스에 위임하여 생성 로직을 중앙 집중화하고, 클라이언트 코드를 구체적인 구현체로부터 분리하는 생성 디자인 패턴입니다.

new를 사용하여 객체를 직접 인스턴스화하는 대신, 팩토리 메서드를 사용합니다:

// 팩토리 없음 - 클라이언트가 구체적인 클래스에 의존함
Notification notification;
if (type.equals("email")) {
    notification = new EmailNotification();
} else if (type.equals("sms")) {
    notification = new SMSNotification();
}

팩토리 패턴을 사용하면, 공통 인터페이스와 구체적인 구현체를 정의합니다:

public interface Notification {
    void send(String message);
}

public class EmailNotification implements Notification {
    public void send(String message) {
        System.out.println("Email: " + message);
    }
}

public class SMSNotification implements Notification {
    public void send(String message) {
        System.out.println("SMS: " + message);
    }
}

정적 생성 메서드를 가진 팩토리 클래스를 생성합니다:

public class NotificationFactory {
    public static Notification create(String type) {
        if (type.equals("email")) {
            return new EmailNotification();
        } else if (type.equals("sms")) {
            return new SMSNotification();
        }
        return null;
    }
}

클라이언트 코드는 직접적인 인스턴스화 대신 팩토리를 사용합니다:

Notification notification = NotificationFactory.create("email");
notification.send("Hello!");  // Output: Email: Hello!

장점: 새로운 타입을 추가할 때 팩토리만 업데이트하면 되며, 클라이언트 코드는 변경되지 않습니다. 이는 인터페이스에 맞춰 프로그래밍한다는 원칙을 따르므로, 시스템을 더 유연하고 확장하기 쉽게 만듭니다.

직접 해보기

import java.util.Scanner;

class Main {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        
        // 두 가지 도형 타입을 읽습니다
        String type1 = scanner.nextLine();
        String type2 = scanner.nextLine();
        
        // TODO: ShapeFactory를 사용하여 첫 번째 도형을 생성합니다
        // 도형이 null이 아니면, draw()를 호출합니다
        // 도형이 null이면, "Unknown shape: [type]"을 출력합니다
        
        // TODO: 두 번째 도형에 대해서도 동일하게 수행합니다
        
    }
}
quiz icon실력 점검

이 레슨에는 짧은 퀴즈가 포함되어 있습니다. 레슨을 시작해 문제를 풀고 진행 상황을 기록하세요.

객체 지향 프로그래밍의 모든 레슨