커맨드 패턴이란 요청을 객체의 형태로 캡슐화하여 사용자가 보낸 요청을 나중에 이용할 수 있도록 메서드 이름, 매개변수 등 요청에 필요한 정보를 저장 또는 로깅, 취소할 수 있게 하는 패턴이다.
struct TV {
func turnOn() {
print("TV가 켜졌습니다")
}
}
struct HomeApp {
private let tv: TV
init(tv: TV) {
self.tv = tv
}
func pressButton() {
tv.turnOn()
}
}
func turnOnTV() {
let tv = TV()
let homeApp = HomeApp(tv: tv)
homeApp.touch()
}
turnOnTV()
// TV가 켜졌습니다
import UIKit
// Command
protocol Command {
func execute()
}
// Concrete Command
struct turnOnTVCommand: Command {
private var tv: TV // Receiver
init(tv: TV) {
self.tv = tv
}
func execute() {
tv.turnOn()
}
}
struct changeChannelCommand: Command {
private var tv: TV // Receiver
private var channel: String
init(tv: TV, channel: String) {
self.tv = tv
self.channel = channel
}
func execute() {
tv.change(channel)
}
}
// Receiver
struct TV {
func turnOn() {
print("TV가 켜졌습니다.")
}
func change(_ channel: String) {
print("TV \(channel)번 채널을 틀었습니다.")
}
}
// Invoker
final class HomeApp {
private var redButton: Command?
private var numberButton: Command?
func setCommand(redButton: Command, numberButton: Command) {
self.redButton = redButton
self.numberButton = numberButton
}
func pressRedButton() {
// Command execute() 호출
redButton?.execute()
}
func pressNumberButton() {
numberButton?.execute()
}
}
let homeApp = HomeApp()
let newTV = TV()
let turnOnTV = turnOnTVCommand(tv: newTV)
let changeChannelOfTV = changeChannelCommand(tv: newTV, channel: "14")
homeApp.setCommand(redButton: turnOnTV, numberButton: changeChannelOfTV)
homeApp.pressRedButton()
homeApp.pressNumberButton()
import UIKit
// Command
protocol Command {
func execute()
}
// Network Service
protocol NetworkService {
func updateProfile(data: ProfileData, completion: @escaping (Result<ProfileData, Error>) -> Void)
}
// Receiver
class ProfileNetworkService: NetworkService {
func updateProfile(data: ProfileData, completion: @escaping (Result<ProfileData, Error>) -> Void) {
// 프로필을 업데이트 하기 위한 네트워크 요청
}
}
// Profile Data
struct ProfileData {
let name: String
let email: String
}
// Update Profile Command
class UpdateProfileCommand: Command {
private let service: NetworkService
private let data: ProfileData
init(service: NetworkService, data: ProfileData) {
self.service = service
self.data = data
}
func execute() {
service.updateProfile(data: data) { result in
switch result {
case .success(let updatedData):
print("Profile updated successfully: \(updatedData)")
case .failure(let error):
print("Failed to update profile: \(error)")
}
}
}
}
// Invoker
class ProfileUpdateViewController: UIViewController {
private let profileService: NetworkService
private var pendingCommands: [Command] = []
init(profileService: NetworkService) {
self.profileService = profileService
super.init(nibName: nil, bundle: nil)
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
func updateUserProfile(with data: ProfileData) {
let command = UpdateProfileCommand(service: profileService, data: data)
command.execute()
pendingCommands.append(command)
}
func retryPendingCommands() {
for command in pendingCommands {
command.execute()
}
pendingCommands.removeAll()
}
}
NetworkServe
와 그 구현체인 ProfileNetworkService
가 이에 해당한다. UpdateProfileCommand
는 NetworkService
를 통해 프로필 업데이트 요청을 보낸다. ProfileUpdateViewController
가 이에 해당한다. 제가 학습한 내용을 요약하여 정리한 것입니다. 내용에 오류가 있을 수 있으며, 어떠한 피드백도 감사히 받겠습니다.
감사합니다.