팩토리 패턴
Coddy PHP 여정의 객체 지향 프로그래밍 섹션에 포함된 레슨 — 91개 중 72번째.
팩토리 패턴(Factory Pattern)은 객체 생성을 별도의 클래스나 메서드에 위임하는 생성 디자인 패턴입니다. 코드 전반에서 new를 직접 사용하는 대신, 팩토리에 객체 생성을 요청합니다.
이 패턴은 공통 인터페이스를 공유하는 여러 관련 클래스가 있고, 특정 조건에 따라 어떤 클래스를 인스턴스화할지 결정하고 싶을 때 특히 유용합니다. 다양한 채널을 통해 메시지를 보낼 수 있는 알림 시스템을 생각해 보세요:
<?php
interface Notification {
public function send(string $message): string;
}
class EmailNotification implements Notification {
public function send(string $message): string {
return "Email: $message";
}
}
class SmsNotification implements Notification {
public function send(string $message): string {
return "SMS: $message";
}
}
팩토리가 없다면, if 문과 new 호출이 곳곳에 흩어지게 될 것입니다. 팩토리는 이 로직을 중앙 집중화합니다:
<?php
class NotificationFactory {
public static function create(string $type): Notification {
return match($type) {
'email' => new EmailNotification(),
'sms' => new SmsNotification(),
default => throw new InvalidArgumentException("Unknown type: $type")
};
}
}
$notification = NotificationFactory::create('email');
echo $notification->send('Hello!');
출력:
Email: Hello!주요 이점은 코드가 구체적인 클래스가 아닌 Notification 인터페이스에 의존한다는 점입니다. 나중에 PushNotification 클래스를 추가하더라도 팩토리만 업데이트하면 됩니다. 팩토리를 사용하는 모든 코드는 수정 없이 자동으로 새로운 타입에 접근할 수 있게 됩니다.
챌린지
쉬움팩토리 패턴(Factory Pattern)을 사용하여 문서 생성기 시스템을 구축해 보겠습니다. 서로 다른 문서 유형(PDF, HTML, Plain Text)은 공통 인터페이스를 공유하지만 서로 다른 출력을 생성합니다. 이는 객체 생성을 팩토리에서 중앙 집중화하기에 완벽한 시나리오입니다.
코드는 다음 네 개의 파일로 구성됩니다:
Document.php— 모든 문서 유형이 따라야 할 계약을 정의하는Document인터페이스를 생성합니다. 이 인터페이스는 콘텐츠를 받아 형식이 지정된 문서 출력을 반환하는 단일 메서드render(string $content): string를 가져야 합니다.Documents.php— Document 인터페이스를 포함하고 이를 구현하는 세 개의 클래스를 생성합니다:PdfDocument—render()메서드는"PDF: [content]"를 반환합니다.HtmlDocument—render()메서드는"<html>[content]</html>"를 반환합니다.TextDocument—render()메서드는"TXT: [content]"를 반환합니다.
DocumentFactory.php— Documents 파일을 포함하고 정적 메서드create(string $type): Document를 가진DocumentFactory클래스를 생성합니다. 이 메서드는match를 사용하여 유형에 따라 적절한 문서 객체를 반환해야 합니다:"pdf"는 새로운PdfDocument를 반환합니다."html"은 새로운HtmlDocument를 반환합니다."text"는 새로운TextDocument를 반환합니다.- 그 외의 유형은
"Unknown document type: [type]"라는 메시지와 함께InvalidArgumentException을 발생시켜야 합니다.
main.php— DocumentFactory 파일을 포함합니다. 문서 유형과 렌더링할 콘텐츠라는 두 개의 입력을 받게 됩니다.팩토리를 사용하여 적절한 문서 유형을 생성한 다음, 콘텐츠와 함께
render()메서드를 호출하고 결과를 출력하세요.새 줄에
"Factory benefit: Adding new types only requires updating the factory"를 출력하여 이 패턴이 왜 가치 있는지 강조하세요.
팩토리 패턴은 코드의 유연성을 유지해 줍니다. 나중에 MarkdownDocument를 추가해야 할 때, 기존의 모든 코드는 변경 없이 그대로 작동하는 동안 팩토리만 업데이트하면 됩니다.
치트 시트
팩토리 패턴(Factory Pattern)은 코드 전반에서 new를 직접 사용하는 대신 객체 생성을 별도의 클래스나 메서드에 위임합니다.
이 패턴은 공통 인터페이스를 공유하는 여러 관련 클래스가 있고, 조건에 따라 어떤 클래스를 인스턴스화할지 결정해야 할 때 유용합니다.
알림 시스템을 예로 들어 보겠습니다:
<?php
interface Notification {
public function send(string $message): string;
}
class EmailNotification implements Notification {
public function send(string $message): string {
return "Email: $message";
}
}
class SmsNotification implements Notification {
public function send(string $message): string {
return "SMS: $message";
}
}
팩토리는 객체 생성 로직을 중앙 집중화합니다:
<?php
class NotificationFactory {
public static function create(string $type): Notification {
return match($type) {
'email' => new EmailNotification(),
'sms' => new SmsNotification(),
default => throw new InvalidArgumentException("Unknown type: $type")
};
}
}
$notification = NotificationFactory::create('email');
echo $notification->send('Hello!'); // Output: Email: Hello!
주요 장점:
- 코드가 구체적인 클래스가 아닌 인터페이스에 의존합니다.
- 새로운 타입을 추가할 때 팩토리만 업데이트하면 됩니다.
- 기존 코드는 수정 없이도 자동으로 새로운 타입에 접근할 수 있습니다.
직접 해보기
<?php
require_once 'DocumentFactory.php';
// 입력 읽기
$type = trim(fgets(STDIN));
$content = trim(fgets(STDIN));
// TODO: DocumentFactory를 사용하여 적절한 문서 유형을 생성하세요
// TODO: content와 함께 render() 메서드를 호출하고 결과를 출력하세요
// TODO: 새 줄에 "Factory benefit: Adding new types only requires updating the factory"를 출력하세요
?>이 레슨에는 짧은 퀴즈가 포함되어 있습니다. 레슨을 시작해 문제를 풀고 진행 상황을 기록하세요.
객체 지향 프로그래밍의 모든 레슨
8매직 메서드
매직 메서드 소개__toString 및 __debugInfo__get, __set, __isset, __unset__call 및 __callStatic__clone 및 객체 복제__serialize 및 __unserialize요약 - 커스텀 컬렉션