패턴이 해결하는 문제 이해

  • 튜플(Tuple) 은 그룹화된 값들의 세트이고, 편리하고, 쉽게 사용할 수 있다. 하지만, 사용하는데 한계가 있다.

var products = [
   ("Kayak", 275.0, 10), 
   ("Lifejacket", 48.95, 14), 
   ("Soccer Ball", 19.5, 32)
];
func calculateTax(product:(String, Double, Int)) -> Double {
   return product.1 * 0.2;
}
func calculateStockValue(tuples:[(String, Double, Int)]) -> Double {
  return tuples.reduce(0, combine: {(total, product) -> Double in
      return total + (product.1 * Double(product.2))
  });
}
print("Sales tax for Kayak: $\(calculateTax(products[0]))");
print("Total value of stock: $\(calculateStockValue(products))");

  • 그림 4-1은 함수들과 튜플 배열 사이의 강력한 결합(Tight Couplings)을 보여준다.

  • 강력한 결합도(Tight Couplings)’ 문제에 대한 이해
    • 강력하게 결합된 컴포넌트가 많은 애플리케이션에서 하나의 변경 사항이 연쇄적인 코드 변경을 필요로 한다.
    • 느슨하게 결합된 컴포넌트가 디자인 패턴을 사용하는 주요한 목표이다.(Loose Couplings)




오브젝트 템플릿 패턴의 이해

  • 오브젝트 템플릿 패턴은 클래스구조체를 이용하여 객체를 생성할 템플릿을 정의한다.
  • 애플리케이션 컴포넌트가 객체가 필요한 경우 스위프트 런타임에 요청한다.

  • 스위프트 런타임의 객체 생성 3단계
    => 이 3단계는 여러 개의 객체를 생성할 때마다 반복적으로 수행된다.

        1. 스위프트 런타임은 해당 템플릿 이름과 초기값들로 객체를 생성한다.
        2. 스위프트 런타임은 객체를 저장할 메모리를 할당하고 템플릿을 이용하여 객체를 생성한다.
          (템플릿에 구현된 객체 초기화 메소드로 초기값을 설정하거나 객체 생성을 요청한 포넌트가 제시한 값을 이용해서 초기화가 이루어진다. 스위프트 런타임은 객체 사용 준비를 위한 초기화를 실행한다.)
        3. 마지막으로 스위프트 런타임은 객체가 생성되었음을 컴포넌트에 알려준다.



      오브젝트 템플릿 패턴 구현

      • 튜플 기반 접근 방법과 흡사하도록 Product 클래스를 생성하기
      class Product {
         var name:String;
         var description:String;
         var price:Double;
         var stock:Int;
         init(name:String, description:String, price:Double, stock:Int) {
             self.name = name;
             self.description = description;
             self.price = price;
             self.stock = stock;
         }
      }
      
      • Product class 사용하기
      var products = [
         Product(name: "Kayak", description: "A boat for one person",
                   price: 275, stock: 10),
         Product(name: "Lifejacket", description: "Protective and fashionable",
                   price: 48.95, stock: 14),
         Product(name: "Soccer Ball", description: "FIFA-approved size and weight",
                   price: 19.5, stock: 32)];
      
      func calculateTax(product:Product) -> Double {
         return product.price * 0.2;
      }
      
      func calculateStockValue(productsArray:[Product]) -> Double {
         return productsArray.reduce(0, {(total, product) -> Double in
             return total + (product.price * Double(product.stock))
         });
      }
      • 스위프트 접근 제어(Access Control)의 이해
        • private: 같은 파일 내부에서만 보이고 구성요소 내에서만 사용할 수 있도록 제한
        • internal
          - 애플리케이션 레벨에서 전체 구성요소의 접근이 가능
          - 같은 프로젝트 내에서 import 구문이 필요없음
        • public
          - 외부에 제공되는 프레임워크 등 API 레벨의 접근 권한
          - Objective-C 쪽으로 코드베이스를 공유할 때 사용 


      오브젝트 템플릿 패턴의 장점

      • 튜플은 훌륭한 기능이지만, 클래스나 구조체를 선호하는 이유는 조정 가능하고 느슨한 결합도를 제공하기 때문.
      • 결합도 감소(decoupling)의 이득
        • 컴포넌트 간의 강력한 결합도를 깬다.
      • 캡슐화(encapsulation)의 이득
        • 데이터와 로직을 하나의 컴포넌트에 넣을 수 있다.
        • 하나의 컴포넌트에 기술되므로 코드 가독성이 올라간다.
      • Public 공개의 이득
        • 객체 사용자에게 제공할 공개 API 가능하게 한다.
        • private으로 구현체를 숨길 수 있다.




      오브젝트 템플릿 패턴의 위험

      • 정확한 종류(클래스 or 구조체)를 선택해야한다.
        • 스위프트에서의 클래스와 구조체의 가장 중요한 차이
          : 클래스는 Reference 객체, 구조체는 Value 객체.
        • 이 차이는 프로토타입 패턴에서 자세히 설명된다.(업데이트 예정)


      정리

      • 본 장에서는 스위프트 개발에 있어 “심장”과 같은 패턴을 설명했다.
      • “심장”은 객체 생성에 사용하는 템플릿의 정의이다.



      Ref. Pro Design Patterns in Swift by Adam Freeman.


      + Recent posts