apple/DesignPattern, Architecture

Swift 디자인패턴 Prototype Pattern (프로토타입 패턴)

lgvv 2022. 5. 28. 16:37

Swift 디자인패턴 Prototype Pattern (프로토타입 패턴)

 

Prototype 패턴은 객체를 새로 생성하는 대신, 기존 객체를 복사하여 새로운 객체를 만드는 생성 패턴. 

 

히스토리

  • 2022-05-28: 디자인 패턴 스터디 정리
  • 2024-11-27: 포스팅 글 재정리 및 조금 더 실용적인 예제 코드로 변경

Prototype Pattern


Prototype Pattern

객체를 빠르게 생성하거나 런타임에 객체의 구조를 동적으로 변경해야 할 때 유용

 

Prototype Pattern은 일반적으로 3개지 개념으로 구성됨

  • Prototype Interface: 객체를 복사할 수 있는 인터페이스(clone) 정의
  • Concrete Prototype: Prototype Interface를 구현하며, 복사 가능한 객체를 생성
  • Client: Prototype 객체를 복사하여 새로운 객체를 생성.

프로토타입 패턴 적용을 고려할 수 있는 상황

  • 복잡한 UI 컴포넌트를 복제 후 수정하여 빠르게 화면 구성

프로토타입 패턴의 장점

  • 빠른 객체 생성: 객체 초기화 비용을 줄일 수 있음.
  • 복잡한 초기화 방지: 새로 생성하는 대신 복사하므로 코드 간소화.
  • 런타임 커스터마이징: 객체를 복제 후 일부 속성만 수정 가능.

프로토타입 패턴의 단점

  • 객체가 다른 객체의 참조를 포함하는 경우 복제 시 참조하는 객체를 어떻게 처리할 지 고민 (깊은 복사 vs 얕은 복사)
  • 객체 간 의존성이 복잡해 질 수 있음

 

코드 예제

Swift에서는 Foundation 내에서 NSCopying을 지원하고 있어서 해당 개념을 구현해보기

 

 

import SwiftUI
import Foundation

protocol Copyable {
    init(_ prototype: Self)
}

extension Copyable {
    func copy() -> Self {
        return type(of: self).init(self)
    }
}

class Monster: Copyable {
    
    var health: Int
    var level: Int
    
    init(health: Int, level: Int) {
        self.health = health
        self.level = level
    }
    
    required convenience init(_ monster: Monster) {
        self.init(health: monster.health, level: monster.level)
    }
}

class EyeballMonster: Monster {
    
    var redness = 0
    
    init(health: Int, level: Int, redness: Int) {
        self.redness = redness
        super.init(health: health, level: level)
    }
    
    required convenience init(_ prototype: Monster) {
        self.init(health: prototype.health,
                  level: prototype.level,
                  redness: 0)
    }
}

private struct ContentView: View {
    var body: some View {
        Button("Execute") {
            // MARK: - Example Usage
            let monster = Monster(health: 700, level: 37)
            let monster2 = monster.copy()
            
            print(monster === monster2)
            
            monster2.level = 30
            print(monster.level, monster2.level)
            
            let eyeball = EyeballMonster(
                health: 3002,
                level: 60,
                redness: 999
            )
            let eyeball2 = eyeball.copy()
            
            print(eyeball2.redness)
        }
    }
}

#Preview {
    ContentView()
}

 

 

결과

 

 

 

 


(참고)

https://www.raywenderlich.com/books/design-patterns-by-tutorials/v3.0/chapters/14-prototype-pattern

 

Design Patterns by Tutorials, Chapter 14: Prototype Pattern

Methods are merely functions that reside in a class. In this chapter, you’ll take a closer look at methods and see how to add methods onto classes that were created by someone else. You’ll also start in on a new project with this chapter: a drawing app

www.kodeco.com:443

 

https://refactoring.guru/ko/design-patterns/prototype

 

프로토타입 패턴

/ 디자인 패턴들 / 생성 패턴 프로토타입 패턴 다음 이름으로도 불립니다: 클론, Prototype 의도 프로토타입은 코드를 그들의 클래스들에 의존시키지 않고 기존 객체들을 복사할 수 있도록 하는 생

refactoring.guru