Notice
Recent Posts
Recent Comments
Link
Tags
- DiffableDataSource
- Human Interface Guidelines
- Apple
- 전달인자 레이블
- 애플사이다
- lineBreakStrategy
- 야곰아카데미
- 디자인패턴
- UIKit
- github
- HIG
- WWDC
- CollectionView
- Split View
- 스위프트
- GOF
- Accessibility
- Keychain
- orthogonalScrollingBehavior
- Combine+UIKit
- 앱개발
- TOSS
- iPad
- IOS
- iTerm
- LanguageGuide
- lineBreakMode
- UILabel
- 애플
- Swift
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 | 31 |
- Today
- Total
애플사이다의 iOS 개발 일지
[디자인 패턴] Abstract Factory - 미리 정해둔 종류로만 객체를 생성할 때 본문
GoF 디자인 패턴 중 하나인 Abstract Factory 패턴을 정리했다.
이 패턴은 예시코드부터 보는 것을 추천한다.
- Ref : 도서 <Dive into Design Patterns>, Alexander Shvets 저
문제 상황
- 가구 판매 앱 개발과정에서 세트 제품군 (a family of reloated products)이 있다. (ex. 의자, 소파, 커피테이블)
또한 해당 세트 제품군에는 여러 스타일의 변형 (variants)이 있다. (ex. 아르데코, 빅토리안, 현대식) - 고객이 가구를 주문하면, 동일한 스타일로 가구세트를 통일해야 하는 상황이다.
또한 새로운 제품 (새로운 스타일)이 자주 추가되므로 매번 기존 코드를 수정하는 번거로움을 피하고 싶다.
패턴 설명
이 패턴은 말로 설명하면 복잡한데, 예시를 보면 매우 쉽다. 😞
- 요약 : Concrete 클래스가 없어도 특정 객체를 생성할 때 항상 미리 지정해 둔 종류로 생성하는 패턴이다.
- 먼저 세트 제품군 종류별 프로토콜을 생성한다. (ex. 의자 프로토콜)
이후 각 스타일의 제품이 위 프로토콜을 채택하도록 한다. (ex. 빅토리안 의자, 모던 의자 등) - 그 다음 Abstract Factory 프로토콜을 선언하고, (ex. FurnitureFactory 프로토콜)
이후 각 스타일마다 위 프로토콜을 채택하도록 한다. (ex. 빅토리안 FurnitureFactory, 모던 FurnitureFactory 등) - 클라이언트는 의자 프로토콜을 사용하여 모든 의자를 항상 동일한 방식으로 주문하게 된다.
(= 의자를 주문하기만 하면 항상 정해진 스타일로 온다는 뜻❗️) - Abstract Factory 패턴은 Factory Method 패턴의 집합을 기반으로 한다.
예시 코드
핵심은 초기화 시 스타일을 지정하면
-> 해당 스타일로 모든 제품군을 생성한다는 것이다.
// MARK: - 1️⃣ Chair
protocol Chair {
func hasLegs()
func sitOn()
}
class VictoryianChair: Chair {
func hasLegs() { }
func sitOn() { }
}
class ModernChair: Chair {
func hasLegs() { }
func sitOn() { }
}
// MARK: - Sofa
protocol Sofa { } // 생략
class VictoryianSofa: Sofa { }
class ModernSofa: Sofa { }
// MARK: - CoffeeTable
protocol CoffeeTable { } // 생략
class VictoryianCoffeeTable: CoffeeTable { }
class ModernCoffeeTable: CoffeeTable { }
// MARK: - 2️⃣ FurnitureFactory
protocol FurnitureFactory {
func createChair() -> Chair
func createSofa() -> Sofa
func createCoffeeTable() -> CoffeeTable
}
class VictorianFurnitureFactory: FurnitureFactory {
func createChair() -> Chair {
print("VictoryianChair")
return VictoryianChair()
}
func createSofa() -> Sofa {
print("VictoryianSofa")
return VictoryianSofa()
}
func createCoffeeTable() -> CoffeeTable {
print("VictoryianCoffeeTable")
return VictoryianCoffeeTable()
}
}
class ModernFurnitureFactory: FurnitureFactory {
func createChair() -> Chair {
print("ModernChair")
return ModernChair()
}
func createSofa() -> Sofa {
print("ModernSofa")
return ModernSofa()
}
func createCoffeeTable() -> CoffeeTable {
print("ModernCoffeeTable")
return ModernCoffeeTable()
}
}
// MARK: - ✅ Client
class House {
let factory: FurnitureFactory
init(factory: FurnitureFactory) { // 1. 초기화 시 스타일을 결정하면
self.factory = factory
}
func service() { // 2. 해당 스타일로 모든 세트 제품을 생성함 ❗️
let chair = factory.createChair()
let sofa = factory.createSofa()
let coffeeTable = factory.createCoffeeTable()
}
}
let victorianFurnitureFactory = VictorianFurnitureFactory()
let victorianHouse = House(factory: victorianFurnitureFactory)
victorianHouse.service()
//VictoryianChair
//VictoryianSofa
//VictoryianCoffeeTable
let modernFurnitureFactory = ModernFurnitureFactory()
let modernHouse = House(factory: modernFurnitureFactory)
modernHouse.service()
//ModernChair
//ModernSofa
//ModernCoffeeTable
활용하는 상황을 상상해보면 아래와 같다.
switch style {
case .victorian:
let victorianFurnitureFactory = VictorianFurnitureFactory()
let victorianHouse = House(factory: victorianFurnitureFactory)
victorianHouse.service()
case .modern:
let modernFurnitureFactory = ModernFurnitureFactory()
let modernHouse = House(factory: modernFurnitureFactory)
modernHouse.service()
// ...
}
장점
- 항상 특정한 종류의 제품만 생성하는 것을 보장할 수 있다.
- Concrete Product와 클라이언트 간의 결합도를 낮춘다.
- Product 초기화 코드를 특정 객체가 전담하므로 단일책임 원칙을 준수한다.
- 새로운 제품 (스타일)이 추가할 때 기존 클라이언트를 훼손하지 않으므로 개방폐쇄 원칙을 준수한다.
단점
- 새로운 프로토콜과 클래스를 추가해야 하므로 코드의 복잡도가 높아진다.
- Reference
🍎 포스트가 도움이 되었다면, 공감🤍 / 구독🍹 / 공유🔗 / 댓글✏️ 로 응원해주세요. 감사합니다.
'프로그래밍 철학' 카테고리의 다른 글
[toss] iOS 개발자를 위한 SIMPLICITY23 리뷰 - 디자이너와 친해지기 (7) | 2023.06.04 |
---|---|
[디자인 패턴] Singleton (0) | 2023.03.26 |
[디자인 패턴] Builder - 초기화 과정이 복잡할 때 (0) | 2023.02.20 |
[디자인 패턴] Factory Method - 비슷한 종류의 타입을 찍어낼 때 (0) | 2023.01.14 |
[디자인 패턴] Memento Pattern - 실행취소 기능이 필요할 때 (2) | 2022.03.23 |
Comments