13-9. 팩토리 패턴 (Factory Pattern)

박은서's avatar
Feb 25, 2026
13-9. 팩토리 패턴 (Factory Pattern)

1. 팩토리 패턴 (Factory Pattern)

1️⃣ 팩토리 패턴이란?

1) 정의

객체 생성 로직을 별도의 Factory에 위임하는 생성 패턴
✔ 객체 생성 책임 분리
✔ 결합도 감소 목적

2) 핵심 개념

“new를 직접 쓰지 않는다”
Animal animal = AnimalFactory.create("dog");
✔ 생성 → Factory 담당
✔ 사용 → Client 담당

2️⃣ 사용 이유

1) 기존 방식 문제

❌ new 남발
❌ 생성 방식 변경 시 수정 범위 큼
❌ 조건문 증가
❌ 결합도 상승

2) 팩토리 적용 효과

✔ 생성 로직 중앙화
✔ 변경 영향 최소화
✔ 확장 용이

3️⃣ 기본 구조

1) Product (인터페이스 / 추상 클래스)

  • 역할 : 객체의 공통 규격 정의
    • 객체들이 따라야 할 타입
    • 클라이언트가 의존하는 대상
    • 구현체 교체 가능하게 만드는 핵심
  • 핵심 키워드 : “무엇을 할 수 있는가 정의”
interface Animal { void speak(); }

2) ConcreteProduct (구현 클래스)

  • 역할 : 실제 객체 구현
    • Product 규격 구현
    • 실제 동작 수행
    • Factory에 의해 생성됨
  • 핵심 키워드 : “실제 기능 제공”
class Dog implements Animal { } class Cat implements Animal { }

3) Factory (생성 담당 클래스)

  • 역할 : 객체 생성 책임 담당
    • 객체 생성 로직 캡슐화
    • 어떤 객체 만들지 결정
    • 클라이언트의 new 제거
  • 핵심 키워드 : “객체 생성 전담”
Animal animal = AnimalFactory.create("dog");

4️⃣ 예시

1) Product

interface Animal { void speak(); }

2) ConcreteProduct

class Dog implements Animal { } class Cat implements Animal { }

3) Factory

class AnimalFactory { public static Animal create(String type) { if (type.equals("dog")) return new Dog(); if (type.equals("cat")) return new Cat(); throw new IllegalArgumentException(); } }

4) Client

Animal animal = AnimalFactory.create("dog");
✔ 구체 클래스 의존 제거

5️⃣ 팩토리 패턴의 장단점

1) 장점

  • Loose Coupling (결합도 감소)
  • 생성 로직 캡슐화
  • 확장성 증가 (OCP 준수)
  • 객체 생성 정책 관리 용이

2) 단점

  • ❌ Factory 클래스 비대화 가능
  • ❌ 조건문 증가 가능
  • ❌ 단순한 경우 과설계

6️⃣ 언제 사용?

  • 생성 과정 복잡
  • 객체 종류 많음
  • 조건 기반 객체 생성
  • 생성 정책 변경 가능성 높음
    • DB 객체 생성
    • UI 컴포넌트
    • 로깅 시스템
    • 게임 캐릭터

7️⃣ 핵심 목적 🚨

  • ❌ new 숨기기 아님 → ✅ 객체 생성 책임 분리

2. 실습 (ex09)

1️⃣ 실습

1) DB.java (인터페이스)

C:\workspace\java_lab\designapp\src\ex09\lib\DB.java
package ex09.lib; public interface DB { void setUrl(String url); int execute(String sql); }
  • 역할
    • 모든 DB 클래스의 공통 규칙 (표준 스펙)
    • “DB라면 반드시 이 기능을 구현해야 함”
  • 목적
    • App은 구체 클래스 몰라도 됨
      • MariaDB인지 OracleDB인지 관심 없음!
      • DB 타입이면 OK!
→ 다형성의 기반

2) Driver.java (enum - 열거형)

C:\workspace\java_lab\designapp\src\ex09\lib\Driver.java
package ex09.lib; public enum Driver { ORACLE("oracle"), MARIA("maria"); private final String protocol; Driver(String protocol) { this.protocol = protocol; } public String getProtocol() { return protocol; } }
  • 역할
    • DB 종류를 표현하는 식별자
    • 문자열 하드코딩 방지
    • 타입 안정성 확보
  • 목적
    • Factory에게 전달하는 선택값
    • 어떤 DB 만들지 알려주는 신호

3) MariaDB.java (구현 클래스)

C:\workspace\java_lab\designapp\src\ex09\lib\MariaDB.java
package ex09.lib; public class MariaDB implements DB { private String path; @Override public int execute(String sql) { if (path == null) { System.out.println("path : null point error"); return -1; } if (sql.equals("select")) { System.out.println("query execute : " + path + "/" + sql); return 1; } else { System.out.println("query fail : syntax error"); return -1; } } @Override public void setUrl(String path) { this.path = path; } }
  • 역할
    • 실제 DB 동작 구현
    • execute(), setUrl() 구체 로직 담당
  • 특징
    • MariaDB 방식으로 동작
    • SQL 처리 방식 정의
    • ➡️ 인터페이스 계약 이행

4) OracleDB.java (구현 클래스)

C:\workspace\java_lab\designapp\src\ex09\lib\OracleDB.java
package ex09.lib; public class OracleDB implements DB { public String url; @Override public int execute(String sql) { if (sql.equals("select")) { System.out.println("query execute : " + url + "/" + sql); return 1; } else { System.out.println("query fail : syntax error"); return -1; } } @Override public void setUrl(String url) { this.url = url; } }
  • 역할
    • Oracle 전용 DB 동작 구현
    • MariaDB와 동일한 인터페이스 사용
  • 목적
    • DB 인터페이스 기반 다형성 실현

5) DBFactory.java (핵심)

C:\workspace\java_lab\designapp\src\ex09\DBFactory.java
package ex09; import ex09.lib.DB; import ex09.lib.Driver; import ex09.lib.MariaDB; import ex09.lib.OracleDB; public class DBFactory { private static DBFactory instance = new DBFactory(); public DBFactory() {} public static DBFactory getInstance() { return instance; } // 단점 : OCP 위배 (새로운 DB 추가해야 할 경우, 이 코드를 수정해야 함) public DB creatDB(Driver driver) { if (driver.getProtocol().equals("maria")) { MariaDB mariaDB = new MariaDB(); mariaDB.setUrl("jdbc:mariadb://127.0.0.1:3306"); return mariaDB; } else if (driver.getProtocol().equals("oracle")) { OracleDB oracleDB = new OracleDB(); oracleDB.setUrl("jdbc:oracle:thin://127.0.0.1:8080"); return oracleDB; } else { throw new NullPointerException("DB driver not found exception"); } } }
  • 역할 (가장 중요 ⭐⭐⭐)
    • 객체 생성 담당
    • 어떤 DB 객체 만들지 결정
    • 초기화(setUrl)까지 처리
  • 책임
    • 객체 생성 책임 집중
    • App에서 제거된 코드(new MariaDB(), new OracleDB())를 Factory가 대신 수행

6) App.java

C:\workspace\java_lab\designapp\src\ex09\App.java
package ex09; import ex09.lib.DB; import ex09.lib.Driver; /** * 팩토리 패턴 예제 */ public class App { public static void main(String[] args) { DBFactory factory = DBFactory.getInstance(); DB db = factory.creatDB(Driver.MARIA); // 팩토리에게 요청! db.execute("select"); } }
  • 역할
    • 프로그램 시작점
    • Factory에게 요청만 함
    • DB 사용만 담당
  • 특징
    • 생성 로직 모름
    • DB 종류 변경 영향 최소화
    • ➡️ 의존성 감소

2️⃣ 실행 흐름 따라가기

▶ 1단계: App 시작

DBFactory factory = DBFactory.getInstance();
App.java
➡️ 싱글톤 Factory 객체 가져옴
⚠️ 이미 DBFactory 내부에 생성되어 있음
private static DBFactory instance = new DBFactory();
DBFactory.java

▶ 2단계: DB 생성 요청

DB db = factory.creatDB(Driver.MARIA);
App.java
App “나는 어떤 DB인지 관심 없음. MARIA 드라이버니까 알아서 만들어줘”

▶ 3단계: Factory 내부 동작 ⭐

public DB creatDB(Driver driver)
DBFactory.java
  • 전달된 값
    • Driver.MARIA
      App.java
  • Driver enum
    • MARIA("maria")
      Driver.java (enum)
      ⬇️
      driver.getProtocol() →"maria"
      DBFactory.java의 creatDB 메서드 내부 if문 조건

▶ 4단계: 조건 분기

if (driver.getProtocol().equals("maria"))
DBFactory.java의 creatDB 메서드 내부 if문 조건
✔ 조건 만족 → MariaDB 객체 생성
MariaDB mariaDB = new MariaDB(); mariaDB.setUrl("jdbc:mariadb://127.0.0.1:3306"); return mariaDB;
DBFactory.java의 creatDB 메서드 내부 if문
➡️ 여기서 이미 URL 세팅까지 완료됨

▶ 5단계: App으로 객체 반환

App이 받는 건:
DB db
⚠ App은 MariaDB 타입이 아닌 인터페이스 타입 반환 받음

▶ 6단계: 실행

db.execute("select");
✔ 실제 호출되는 건 → MariaDB.execute()

▶ 콘솔 출력 과정

  • MariaDB 내부
    • System.out.println("query execute : " + path +"/" + sql);
  • 출력 결과
    • queryexecute : jdbc:mariadb://127.0.0.1:3306/select
Share article