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();➡️ 싱글톤 Factory 객체 가져옴
⚠️ 이미 DBFactory 내부에 생성되어 있음
private static DBFactory instance = new DBFactory();▶ 2단계: DB 생성 요청
DB db = factory.creatDB(Driver.MARIA);App “나는 어떤 DB인지 관심 없음. MARIA 드라이버니까 알아서 만들어줘”
▶ 3단계: Factory 내부 동작 ⭐
public DB creatDB(Driver driver)- 전달된 값
Driver.MARIA
- Driver enum
MARIA("maria")⬇️
driver.getProtocol() →"maria"▶ 4단계: 조건 분기
if (driver.getProtocol().equals("maria"))✔ 조건 만족 → MariaDB 객체 생성
MariaDB mariaDB = new MariaDB();
mariaDB.setUrl("jdbc:mariadb://127.0.0.1:3306");
return mariaDB;➡️ 여기서 이미 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/selectShare article