Builder Pattern
- ๋ณต์กํ ๊ฐ์ฒด๋ฅผ ๋จ๊ณ๋ณ๋ก ๊ตฌ์ถํ๋ ์์ฑ ๋์์ธ ํจํด
์ฌ์ฉ ์ด์
alert
์ ๊ฒฝ์ฐ ์ํฉ์ ๋ฐ๋ผ ๋ค์ํ UI๊ฐ ๋์ฌ ์ ์๋ค.
- ์ฆ, ์ด๋ค Case์๋ โํ์ธโ, โ์ทจ์โ ๋ฒํผ ๋ชจ๋ ํ์ํ ์๋ ์๊ณ , ์ด๋ค Case์๋ โํ์ธโ ๋ฒํผ๋ง ํ์ํ ์ ์๋ค.
- ๋ฐ๋ผ์, ์ํฉ์ ๋ฐ๋ผ ์กฐํฉ๋ ์ ์๋ ๊ฒฝ์ฐ์ ์๊ฐ ๋ค์ํ ๊ฒฝ์ฐ ์ด
Builder Pattern
์ ์ฌ์ฉํ๋ ๊ฒ์ด ์ ์ ํ๋ค.
๊ธฐ๋ณธ ๊ตฌ์กฐ
- ๋น๋ ํจํด์ 4๊ฐ์ง ๊ธฐ๋ณธ ๊ตฌ์กฐ๋ฅผ ๊ฐ์ง๋ค.
- Builder: ๊ฐ์ฒด์ ๊ตฌ์ฑ ์์๋ฅผ ์ ์ํ๋ ์ธํฐํ์ด์ค
- Concrete Builder: ์ธํฐํ์ด์ค๋ฅผ ๊ตฌํํ๊ณ , ๊ฒฐ๊ณผ๋ฌผ์ ๋ฐํํ๋ ๋ฐฉ์์ ์ ์
- Director: ์ธํฐํ์ด์ค๋ฅผ ์ฌ์ฉํ์ฌ ๊ฐ์ฒด๋ฅผ ์์ฑํ๋ ๊ณผ์ ์ ์ ์
- Product: ๋น๋๋ฅผ ํตํด์ ์์ฑ๋๋ ์ต์ข ๊ฐ์ฒด
์ฅ์
- ๋ถ๋ฆฌ๋ ๊ตฌ์ถ ๊ณผ์ : ๊ฐ์ฒด์ ๊ตฌ์ถ๊ณผ ํํ์ ๋ถ๋ฆฌํ์ฌ ๋ณต์กํ ๊ฐ์ฒด๋ฅผ ์ฝ๊ฒ ์์ฑ
- ์ฌ์ฌ์ฉ์ฑ: ๋์ผํ ๊ตฌ์ถ ๊ณผ์ ์์ ๋ค์ํ ํํ ๊ฐ๋ฅ
- ๊ฐ๋ ์ฑ: ๊ฐ ๋จ๊ณ๊ฐ ๋ช ํํ ์ ์๋์ด ์์ด, ์ฝ๋์ ๊ฐ๋ ์ฑ์ด ์ข์์ง๋ค.
๋จ์
- ๋ณต์ก์ฑ ์ฆ๊ฐ: ๋จ์ํ ๊ฐ์ฒด์ ๋น๋ ํจํด์ ์ฌ์ฉํ๋ฉด ๋ถํ์ํ๊ฒ ๋ณต์ก์ฑ์ ์ฆ๋์ํฌ ์ ์๋ค.
1. Builder ๊ตฌํ
Builder
๋ ๊ฐ์ฒด์ ๊ตฌ์ฑ์์๋ฅผ ์ ์ํ๋Class
์ด๋ค.
Alert
์ ๊ฒฝ์ฐ,title
,message
,action
๊ณผ ๊ฐ์ ๊ธฐ๋ณธ ์์๋ฅผ ๊ฐ์ง๋ค.
- ๋ฐ๋ผ์, ์์ ๊ฐ์ ๊ตฌ์ฑ ์์๋ฅผ
protocol
์ ํ์ฉํด ์ ์ํด์ค๋ค.
//
// Protocol+Builder.swift
// AlertBuilderPattern
//
// Created by Dongwan Ryoo on 1/7/24.
//
import Foundation
//class์์๋ง ์ค์ํ ์ ์์
protocol Builder: AnyObject {
//alert์ title๊ณผ message
var title: String? { get }
var message: String? { get }
//alert์ title, message, ConfirmAction์ ์ถ๊ฐํ๋ ๋ฉ์๋
func setTitle(_ text: String) -> Self
func setMessage(_ text: String) -> Self
func addConfirmAction(_ text: String, action: (() -> Void)?) -> Self
}
2. Concrete Builder ๊ตฌํ
Builder
๋ฅผ ๊ตฌํํ์ผ๋, ์ด ์ธํฐํ์ด์ค๋ฅผ ์ฑํํConcrete Builder
๋ฅผ ๊ตฌ์ฑํ๋ค.
Concrete Builder
์ ํต์ฌ์ 1)์ธํฐํ์ด์ค ๊ตฌํํ๊ณ , 2)๊ฒฐ๊ณผ๋ฌผ์ ์ ์ํ๊ณ , 3)์ด๋ฅผ ๋ฐํํ ๋ฐฉ์์ ์ ์ํ๋ ๊ฒ์ด๋ค.
- ์ธํฐํ์ด์ค ๊ตฌํ
Builder protocol
์ ์ฑํํ๋ค.
import Foundation
class AlertConcreteBuilder: Builder {
var title: String?
var message: String?
func setTitle(_ text: String) -> Self {
}
func setMessage(_ text: String) -> Self {
}
func addConfirmAction(_ text: String, action: (() -> Void)?) -> Self {
}
}
2)๊ฒฐ๊ณผ๋ฌผ์ ์ ์
- ๋ฐํํ ๊ฒฐ๊ณผ๋ฌผ์ Customํ AlertController์ด๊ธฐ ๋๋ฌธ์, ๋ณ๋์
CustomAlertController
ํ์ผ์ ์์ฑํด์ค๋ค.
//
// CustomAlertController.swift
// AlertBuilderPattern
//
// Created by Dongwan Ryoo on 1/7/24.
//
import UIKit
class CustomAlertController: UIViewController {
}
- ๊ฒฐ๊ณผ๋ฌผ(
Alert
)์ ๋ค์ด๊ฐ UI ๋ฑ์ ์ ์ํด์ค๋ค.
import UIKit
import SnapKit
class CustomAlertController: UIViewController {
private lazy var alertView = {
let view = UIStackView()
view.layer.cornerRadius = 16
view.backgroundColor = .bgGrey
view.axis = .vertical
view.alignment = .center
return view
}()
private lazy var titleLabel = {
let view = UILabel()
view.font = UIFont.systemFont(ofSize: 16, weight: .bold)
view.textAlignment = .center
return view
}()
private lazy var messageLabel = {
let view = UILabel()
view.font = UIFont.systemFont(ofSize: 12)
view.textAlignment = .center
return view
}()
private lazy var confirmButton = {
let view = UIButton()
view.setTitleColor(.white, for: .normal)
view.titleLabel?.font = UIFont.systemFont(ofSize: 14, weight: .bold)
view.backgroundColor = .mainBlue
view.layer.cornerRadius = 16
return view
}()
override func viewDidLoad() {
addTarget()
layouts()
}
}
extension CustomAlertController {
func layouts() {
view.addSubview(alertView)
alertView.snp.makeConstraints {
$0.width.equalTo(312)
$0.center.equalToSuperview()
}
alertView.addArrangedSubview(titleLabel)
titleLabel.snp.makeConstraints {
$0.top.equalToSuperview().offset(24)
$0.width.equalTo(276)
$0.centerX.equalToSuperview()
}
alertView.addArrangedSubview(messageLabel)
alertView.setCustomSpacing(12, after: titleLabel)
messageLabel.snp.makeConstraints {
$0.width.equalTo(276)
$0.centerX.equalToSuperview()
}
alertView.addArrangedSubview(confirmButton)
alertView.setCustomSpacing(24, after: messageLabel)
confirmButton.snp.makeConstraints {
$0.centerX.equalToSuperview()
$0.width.equalTo(276)
$0.height.equalTo(44)
}
}
}
extension CustomAlertController {
func addTarget() {
confirmButton.addTarget(self, action: #selector(confirmButtonTapped), for: .touchUpInside)
}
@objc
func confirmButtonTapped() {
dismiss(animated: true)
}
}
- ๊ฒฐ๊ณผ๋ฌผ์ ๋ค์ด๊ฐ
title
,massage
๋ฅผ ๋ฐ์ ํ๋กํผํฐ๋ฅผ ์์ฑํ๋ค.
class CustomAlertController: UIViewController {
var alertTitle: String?
var alertMessage: String?
private lazy var alertView = {
let view = UIStackView()
view.layer.cornerRadius = 16
view.backgroundColor = .bgGrey
view.axis = .vertical
view.alignment = .center
return view
}()
.
.
.
//๊ธฐ์กด ์ฝ๋
- ๋ฒํผ์
Action
์ ์ ์ํ ๊ตฌ์กฐ์ฒด๋ฅผ ๋ง๋ค์ด ์ค๋ค.
- ์ด๋, ๋ฒํผ์ ๋ค์ด๊ฐ
ํ ์คํธ
์Action
์ ๊ฐ์ด ์ ์ํด์ค๋ค.
struct Action {
var text: String?
var action: (()-> Void)?
}
CustomAlertController
์action
ํ๋กํผํฐ๋ฅผ ์ถ๊ฐํด์ค๋ค.
class CustomAlertController: UIViewController {
var alertTitle: String?
var alertMessage: String?
var confirmAction: Action?
private lazy var alertView = {
let view = UIStackView()
view.layer.cornerRadius = 16
view.backgroundColor = .bgGrey
view.axis = .vertical
view.alignment = .center
return view
}()
.
.
.
//๊ธฐ์กด ์ฝ๋
- ์ธํฐํ์ด์ค์ ๊ตฌ์ฑ ์์(
title
,message
,action
)๋ฅผ UI์ ์ ์ฉํด์ค๋ค.
private lazy var titleLabel = {
let view = UILabel()
view.font = UIFont.systemFont(ofSize: 16, weight: .bold)
view.textAlignment = .center
view.text = alertTitle //Title
return view
}()
private lazy var messageLabel = {
let view = UILabel()
view.font = UIFont.systemFont(ofSize: 12)
view.textAlignment = .center
view.text = alertMessage //Message
return view
}()
private lazy var confirmButton = {
let view = UIButton()
view.setTitleColor(.white, for: .normal)
view.titleLabel?.font = UIFont.systemFont(ofSize: 14, weight: .bold)
view.backgroundColor = .mainBlue
view.layer.cornerRadius = 16
view.setTitle(confirmAction?.text, for: .normal) //Button Title
return view
}()
.
.
.
@objc
func confirmButtonTapped() {
confirmAction?.action?() //Button Action
dismiss(animated: true)
}
- ์ง๊ธ๊น์ง ์ธํฐํ์ด์ค๋ฅผ ๊ตฌํํ๊ณ , ๋ฐํํ ๊ฒฐ๊ณผ๋ฌผ(
CustomAlertController
)์ ์ ์ํ๋ค.
- ์ด์ ,
AlertConcreteBuilder
๋ก ๋์๊ฐ์ ๊ฒฐ๊ณผ๋ฌผ์ ๋ฐํํ ๋ฐฉ์์ ์ ์ํ๋ฉด ๋๋ค.
- ๊ฒฐ๊ณผ๋ฌผ ๋ฐํ ๋ฐฉ์ ์ ์
AlertConcreteBuilder
๋ก ๋์๊ฐ์ ์ ์๋ ๊ฒฐ๊ณผ๋ฌผ์ ์ธ์คํด์ค๋ฅผ ์์ฑํด์ค๋ค.
class AlertConcreteBuilder: Builder {
var title: String?
var message: String?
private let alertViewController = CustomAlertController()
func setTitle(_ text: String) -> Self {
}
func setMessage(_ text: String) -> Self {
}
func addConfirmAction(_ text: String, action: (() -> Void)?) -> Self {
}
}
Alert
์ ๊ฒฝ์ฐ ํน์ ViewController
๋ฅผ ๋ฃจํธ๋ก ํ๊ธฐ ๋๋ฌธ์RootViewController
๋ ํ๋ ์ ์ํด์ค๋ค.
class AlertConcreteBuilder: Builder {
var title: String?
var message: String?
private let alertViewController = CustomAlertController()
private var rootViewController: UIViewController?
func setTitle(_ text: String) -> Self {
}
func setMessage(_ text: String) -> Self {
}
func addConfirmAction(_ text: String, action: (() -> Void)?) -> Self {
}
}
- ํ์ธ ๋ฒํผ์ ํด๋ฆญํ์ ๋์ ์ก์ ๋ ์ ์ํด์ค๋ค.
class AlertConcreteBuilder: Builder {
private var title: String?
private var message: String?
private var addConfirmAction: Action?
private let alertViewController = CustomAlertController()
private var rootViewController: UIViewController?
func setTitle(_ text: String) -> Self {
}
func setMessage(_ text: String) -> Self {
}
func addConfirmAction(_ text: String, action: (() -> Void)?) -> Self {
}
}
AlertConcreteBuilder
๋ฅผ ๊ฑฐ์ณ ๊ฒฐ๊ณผ๋ฌผ์ ์ ๋ฌํ ์์๋ค์ ๋ฉ์๋ ๋ด๋ถ์ ๊ตฌํํด์ค๋ค.
class AlertConcreteBuilder: Builder {
var title: String?
var message: String?
private var addConfirmAction: Action?
private let alertViewController = CustomAlertController()
private var rootViewController: UIViewController?
func setTitle(_ text: String) -> Self {
title = text
return self
}
func setMessage(_ text: String) -> Self {
message = text
return self
}
func addConfirmAction(_ text: String, action: (() -> Void)?) -> Self {
addConfirmAction?.text = text
addConfirmAction?.action = action
return self
}
}
rootViewController
๋ฅผ ์ ์ํ ์์ฑ์๋ฅผ ๋ง๋ค์ด์ค๋ค.
- ๋ง์ง๋ง์ผ๋ก
present()
๋ฉ์๋๋ฅผ ํตํด ๊ฒฐ๊ณผ๋ฌผ์ ๋ฐํํด์ค๋ค.
class AlertConcreteBuilder: Builder {
var title: String?
var message: String?
private var addConfirmAction: Action?
private let alertViewController = CustomAlertController()
private var rootViewController: UIViewController?
init(_ viewController: UIViewController) {
rootViewController = viewController
}
func setTitle(_ text: String) -> Self {
title = text
return self
}
func setMessage(_ text: String) -> Self {
message = text
return self
}
func addConfirmAction(_ text: String, action: (() -> Void)?) -> Self {
addConfirmAction?.text = text
addConfirmAction?.action = action
return self
}
@discardableResult
func present() -> Self {
alertViewController.alertTitle = title
alertViewController.alertMessage = message
alertViewController.confirmAction = addConfirmAction
alertViewController.modalPresentationStyle = .overFullScreen
alertViewController.modalTransitionStyle = .crossDissolve
rootViewController?.present(alertViewController, animated: true)
return self
}
}
3. Product ๊ตฌ์ฑ
Director
๋ ์ง๊ธ ์ํฉ์์๋ ๋ณต์ก๋๋ง ๋๋ฆฌ๊ธฐ ๋๋ฌธ์ ์์ฑ X
ViewController
์Product
์์ฑ
//
// ViewController.swift
// AlertBuilderPattern
//
// Created by Dongwan Ryoo on 1/7/24.
//
import UIKit
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = .black
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(true)
showAlert()
}
func showAlert() {
AlertConcreteBuilder(self)
.setTitle("์๋ฆผ์ ํ์ธํด์ฃผ์ธ์.")
.setMessage("๊ถํ์ ํ์ธํ๊ณ ์ถ์ต๋๋ค.")
.addConfirmAction("ํ์ธ") {
print("ํ์ธ ๋ฒํผ ํด๋ฆญ")
}
.present()
}
}
4. ์ต์ข ๊ฒฐ๊ณผ๋ฌผ

Share article