Notice
Recent Posts
Recent Comments
Link
Tags
- Accessibility
- WWDC
- 스위프트
- 애플
- iPad
- DiffableDataSource
- 애플사이다
- UILabel
- orthogonalScrollingBehavior
- Split View
- UIKit
- Combine+UIKit
- Apple
- CollectionView
- 전달인자 레이블
- 디자인패턴
- HIG
- 야곰아카데미
- GOF
- lineBreakMode
- LanguageGuide
- Human Interface Guidelines
- IOS
- Keychain
- 앱개발
- iTerm
- Swift
- github
- lineBreakStrategy
- TOSS
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
- Today
- Total
애플사이다의 iOS 개발 일지
[디자인 패턴] Factory Method - 비슷한 종류의 타입을 찍어낼 때 본문
GoF 디자인 패턴 중 하나인 Factory Method 패턴을 정리했다.
- Ref : 도서 <Dive into Design Patterns>, Alexander Shvets 저
문제 상황
- 물류관리 앱을 개발하는 과정에서 먼저 Truck (트럭) 운송 처리 로직을 만들었는데, 얼마 뒤 Ship (선박) 등 추가적인 운송수단 처리가 필요하게 됐다.
- 대부분의 코드가 기존의 Truck 클래스에 결합되어 있어 코드 재사용성이 떨어지는 문제가 있는 상황이다.
패턴 설명
- 요약 : 부모클래스에서 객체 생성 인터페이스를 제공하며, 동시에 자식클래스가 객체의 유형을 변경하여 생성 가능하도록 하는 패턴이다.
- Product, Creator 역할이 필요하다.
1. Product
- 일반적인 객체 생성 코드를 부모클래스의 팩토리 메서드 내부에 배치한다.
팩토리 메서드는 생성한 객체를 반환하며, 이 객체를 Product (제품)라고 부른다. - 현재 문제상황에서 Product는 Transport (Truck, Ship 등)이다.
- 여러 종류의 Product는 공통적인 프로토콜을 채택해야 한다.
- 클라이언트 (팩토리 메서드를 사용하는 코드)는 Product 간의 차이를 모른다.
2. Creator
- 위에서 설명한 부모클래스 역할을 Creator 클래스가 한다.
- 현재 문제상황에서 Creator는 Logistics (RoadLogistics, SeaLogistics 등)이다.
- 이제 자식클래스에서 팩토리 메서드를 override하여 반환하는 Product 타입을 변경할 수 있다.
- 네이밍에서 예상되는 것과 달리, Creator의 책임은 제품을 생성하는 게 아니라 제품과 관련된 핵심 비즈니스 로직을 처리하는 것이다. 팩토리 메서드는 이러한 비즈니스 로직을 Concrete Product 클래스로부터 분리 (디커플링)하는 데 도움을 준다.
예시 코드
부모클래스 Logistics는 팩토리 메서드에서 Truck (default transport 개념)을 생성하도록 했고,
자식클래스인 Road/SeaLogistics는 팩토리 메서드를 override하여 각각 Truck/Ship을 자체적으로 생성한다.
// MARK: - 1️⃣ Product
protocol Transport {
func deliver()
}
class Truck: Transport { // Concrete Product-1
func deliver() {
print("Truck - delivery started")
}
}
class Ship: Transport { // Concrete Product-2
func deliver() {
print("Ship - delivery started")
}
}
// MARK: - 2️⃣ Creator
class Logistics {
func createTransport() -> Transport {
let defaultTransport = Truck()
print("Truck - created")
return defaultTransport
}
func service() {
let transport: Transport = createTransport()
print("Packages on board")
transport.deliver()
}
}
class RoadLogistics: Logistics { // Concrete Creator-1
override func createTransport() -> Transport {
print("Truck - created")
return Truck()
}
}
class SeaLogistics: Logistics { // Concrete Creator-2
override func createTransport() -> Transport {
print("Ship - created")
return Ship()
}
}
// MARK: - ✅ Client
let roadLogistics = RoadLogistics()
roadLogistics.service()
//Truck - created
//Packages on board
//Truck - delivery started
let seaLogistics = SeaLogistics()
seaLogistics.service()
//Ship - created
//Packages on board
//Ship - delivery started
활용안을 상상해보면 아래 형태일듯
if destinationType == .sameLand {
let roadLogistics = RoadLogistics()
roadLogistics.service()
} else {
let seaLogistics = SeaLogistics()
seaLogistics.service()
}
장점
- 데이터베이스 연결, 파일시스템, 네트워크 등 대규모 객체를 처리하는 상황에서 시스템 리소스를 절약할 수 있다.
- Creator와 Concrete Product의 결합도를 낮춘다.
- 제품 초기화 기능을 한 객체에서 전담하므로 단일책임 원칙을 준수한다.
- 클라이언트 코드에 영향을 주지 않은 채로 새로운 Product를 도입할 수 있으므로 개방폐쇄 원칙을 준수한다.
단점
- 새로운 자식클래스를 생성해야 하므로 코드 복잡도가 높아진다.
따라서 Creator 클래스의 기존 계층구도에 패턴을 도입하는 것이 좋다.
- Reference
🍎 포스트가 도움이 되었다면, 공감🤍 / 구독🍹 / 공유🔗 / 댓글✏️ 로 응원해주세요. 감사합니다.
'프로그래밍 철학' 카테고리의 다른 글
[toss] iOS 개발자를 위한 SIMPLICITY23 리뷰 - 디자이너와 친해지기 (7) | 2023.06.04 |
---|---|
[디자인 패턴] Singleton (0) | 2023.03.26 |
[디자인 패턴] Builder - 초기화 과정이 복잡할 때 (0) | 2023.02.20 |
[디자인 패턴] Abstract Factory - 미리 정해둔 종류로만 객체를 생성할 때 (0) | 2023.01.16 |
[디자인 패턴] Memento Pattern - 실행취소 기능이 필요할 때 (2) | 2022.03.23 |
Comments