Notice
Recent Posts
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
Tags
- TDD
- IOS
- five lines of cdde
- ARC
- unittest
- 카카오맵클론
- alamofire
- 프로그래머스
- 코딩테스트입문
- algorithm
- five lines of code
- Swift디자인패턴
- ios면접
- mrc
- RC
- firestore
- RxSwift
- hackerrank
- Di
- Safari Inspector
- Swift코딩테스트
- storekit2
- 리팩터링
- SWIFT
- AutoLayout
- firebase
- UIKit
- 클린코드
- 앱의생명주기
- css학습
Archives
- Today
- Total
샘성의 iOS 개발 일지
[디자인 패턴] 추상 팩토리 패턴 본문
728x90
서로 연관되거나 의존적인 객체들의 조합을 만드는 인터페이스를 제공하는 생성자 패턴
팩토리 메서드 패턴과의 차이점?
- 팩토리 매서드
- 1 팩토리 - 1 객체 생성
- 구체적 객체 생성 과정을 하위 클래스에 구현하도록 하는 것이 point
- → 메서드 레벨에서의 구체화된 인스턴스의 생성 및 구성에 대한 의존성 감소
- 추상 팩토리
- 1 팩토리 - 연관된 여러 종류의 객체 생성
- 연관된 여러 종류 객체의 묶음을 구체적인 클래스에 의존하지 않고 생성 가능하도록 하는 것이 point
- 클래스 레벨에서의 구체화된 객체의 생성 및 구성에 대한 의존성 감소
Swift 예제 코드
/*
[배경]
이전 View에서 **애플 키보드 마우스 세트** or **윈도우 키보드 마우스 세트**를 유저가 선택 할 수 있는 상황
이전 View에서 어떤 세트를 선택했느냐에 따라 결제 View를 다르게 띄워줘야 한다.
*/
enum TechBrand: CaseIterable {
case apple
case window
}
// 추상 팩토리 인터페이스 - 연관된 추상 제품들을 반환하는 메서드들의 집합
protocol KeyboardMouseFactory {
func createMouse() -> Mouse
func createKeyboard() -> Keyboard
}
struct AppleKeyboardMouseFactory: KeyboardMouseFactory {
func createMouse() -> any Mouse {
return AppleMouse()
}
func createKeyboard() -> any Keyboard {
return AppleKeyboard()
}
}
struct WindowKeyboardMouseFactory: KeyboardMouseFactory {
func createMouse() -> any Mouse {
return WindowMouse()
}
func createKeyboard() -> any Keyboard {
return WindowKeyboard()
}
}
// 이미 선택된 TechBrand에 따라 다른 '키보드 + 마우스 세트'를 보여줘야하는 결제 화면
final class PurchaseViewController: UIViewController {
private var keyboardMouseFactory: KeyboardMouseFactory
private lazy var keyboard: Keyboard = keyboardMouseFactory.createKeyboard()
private lazy var mouse: Mouse = keyboardMouseFactory.createMouse()
// 팩토리 유형이 선택된 TechBrand에 따라 유연하게 바뀐다.
init(selected type: TechBrand) {
switch type {
case .apple:
self.keyboardMouseFactory = AppleKeyboardMouseFactory()
case .window:
self.keyboardMouseFactory = WindowKeyboardMouseFactory()
}
}
.
.
.
func getTotalPrice() {
print(self.keyboard.price + self.mouse.price)
}
}
// 마우스
protocol Mouse {
var price: Int { get }
func click()
func scroll()
}
struct AppleMouse: Mouse {
var price: Int = 70000
func click() {
print("애플 마우스 - 클릭")
}
func scroll() {
print("애플 마우스 - 스크롤")
}
}
struct WindowMouse: Mouse {
var price: Int = 50000
func click() {
print("윈도우 마우스 - 클릭")
}
func scroll() {
print("윈도우 마우스 - 스크롤")
}
}
// 키보드
protocol Keyboard {
var price: Int { get }
func type(_ letter: String)
}
struct AppleKeyboard: Keyboard {
var price: Int = 130000
func type(_ letter: String) {
print("애플 키보드 -'\\(letter)'")
}
}
struct WindowKeyboard: Keyboard {
var price: Int = 110000
func type(_ letter: String) {
print("윈도우 키보드 -'\\(letter)'")
}
}
// 1. 애플 세트 선택
let applePurchaseViewController = PurchaseViewController(selected: .apple)
applePurchaseViewController.getTotalPrice() >> 200000
// 2. 윈도우 세트 선택
let windowPurchaseViewController = PurchaseViewController(selected: .window)
windowPurchaseViewController.getTotalPrice() >> 160000
언제 사용하면 좋을까?
💡 객체 생성 과정을 추상화하여 코드의 유연성과 유지보수성을 높이고 결합도를 낮추는 데 큰 장점이 있다
- 클라이언트 단에서 구체적인 클래스를 모를 때
- 서로 연관된 여러 객체들을 함께 생성해야 할 때
주의 할 점
- 추상 팩토리 인터페이스에 연관되는 객체가 새로 추가 될 때마다 바꿔야 한다.
- e.g.) KeyboardMouseFactory에 ‘키링’이 추가 된 경우, AppleKeyboardMouseFactory, WindowKeyboardMouseFactory에 키링에 관련된 코드를 추가해야한다. → 번거로움
참고:
https://inpa.tistory.com/entry/GOF-💠-추상-팩토리Abstract-Factory-패턴-제대로-배워보자
https://refactoring.guru/ko/design-patterns/abstract-factory
728x90
'iOS > HIG & 디자인 패턴' 카테고리의 다른 글
[디자인 패턴] 팩토리 메서드 패턴 (0) | 2024.06.18 |
---|---|
[HIG] Launching - 실제 적용하여 리펙토링 하기(1) (0) | 2023.11.15 |