-
Swift4: Protocol Oriented Programming - 7.스위프트에서 디자인 패턴 적용 - (2) 구조 패턴POP 2021. 2. 24. 21:03
구조 패턴
어떻게 타입을 더 큰 구조체로 결합할 수 있는가를 서술. 더 큰 구조체는 작업하기 쉽고, 복잡도를 감추기에 좋다. 구조 패턴의 대부분의 패턴들은 객체 간의 연결을 수반한다.
-
어댑터(Adapter)
공존할 수 없는 인터페이스를 가진 타입을 합께 작동하게 해준다.
-
브리지(Bridge)
구현체로부터 타입의 추상적 요소를 분리하는데 사용, 둘은 달라질 수 있다.
-
컴포지트(Composite)
객체 그룹을 하나의 객체로 다룸
-
데코레이터(Decorator)
객체에 이미 존재하는 메소드에 행위를 추가하거나 오버라이드
-
퍼사드(Facade)
더 크고 복잡한 코드를 위한 단순화된 인터페이스 제공
-
플라이웨이트(Flyweight)
생성해야 하는 리소스를 줄이고 많은 유사 객체를 사용하도록 해준다.
-
프록시(Proxy)
다른 클래스나 여러 클래스를 위해 인터페이스처럼 행동하는 타입
브리지 패턴
구현체에서 추상화를 분리한다. 두 계층을 가진 추상화와 유사
-
문제
새로운 기능이 추가되면서 시간이 지남에 따라 새로운 요구 사항으로 나타나는 경향이 있는 문제. 새로운 요구 사항과 기능이 들어오면 상호작용하는 방식을 변경해야 한다. 브리지 패턴으로 코드를 리팩토링 하지 않고, 해결할 수 있다. 보통 객체지향 프로그래밍에서 클래스 계층 증가 현상으로 알려져 있다.
-
해결
상호작용하는 기능을 갖고 기능 간에 공유하는 능력으로 부터 각 기능에 특화된 기능을 분리. 그 후 하나로 모음으로써 공유되는 기능을 캡슐화한다.
// 작업 단위를 하나로 묶는 브릿지 타입 생성 struct MessageBridge { static func sendMessage(message: Message, sender: Sender) { var sender = sender message.prepareMessage() sender.message = message sender.verifyMessage() sender.sendMessage() } }
퍼사드 패턴
크고 복잡한 코드에 간소화된 인터페이스 제공. 여러 API를 하나의 더 사용하기 쉬운 API로 결합하게 해준다.
-
문제
함께 작동하게 설계된 수 많은 독립적인 API를 가진 복잡한 시스템. 작업을 수행하기 위해 서로 긴밀히 작동하는 여러 API가 있는 경우. 어떠한 작업을 수행하기 위해 여러 개의 API가 함께 동작하는 경우.
-
해결
API의 복잡성을 간단한 인터페이스 뒤로 숨긴다. 느슨한 결합을 통해 API를 사용하는 모든 코드를 리팩토링하지 않으면서 API를 변경할 수 있도록 해준다.
struct RentalCar { // 렌터카에 대한 정보 } struct RentalCarBooking { static func getRentalCarNameForDates(to: Date, from: Date) -> [RentalCar]? { let cars = [RentalCar]() // 렌터카를 가져오는 로직 return cars } static func bookRentalCar(rentalCar: RentalCar) { // 렌터카를 예약하는 로직 } } // 퍼사드 패턴 구현 struct TravelFacade { var hotels: [Hotel]? var flights: [Flight]? var cars: [RentalCar]? // 각각의 API에 직접 접근할 필요 없이 이 타입을 사용하여 검색, 예약할 수 있다. init(to: Date, from: Date) { hotels = HotelBooking.getHotelNameForDates(to: to, from: from) flights = FlightBooking.getFlightNameForDates(to: to, from: from) cars = RentalCarBooking.getRentalCarNameForDates(to: to, from: from) } func bookTrip(hotel: Hotel, flight: Flight, rentalCar: RentalCar) { HotelBooking.bookHotel(hotel: hotel) FlightBooking.bookFlight(flight: flight) RentalCarBooking.bookRentalCar(rentalCar: rentalCar) } }
프록시 디자인 패턴
어느 한 가지 타입이 다른 타입 또는 API를 위한 인터페이스로 동작할 수 있다. 프록시라 부르는 래퍼 클래스로 객체에 기능을 추가하거나 API의 구현부를 숨기거나 객체의 접근을 제한 시킬 수 있다.
-
문제
API와 코드 사이에 추상 레이어를 생성해야만 하는 경우.
API를 변경해야 하는데 관련 코드를 갖고 있지 않거나 애플리케이션 내의 어딘가에 이미 해당 API에 대한 의존성이 있는 경우
-
해결
다른 타입이나 API와 상호작용을 하기 위해 인터페이스처럼 동작하는 타입을 생성해야 한다.
// 코드와 원격 API 사이에 추상 계층을 추가 // iTunes API에 정보를 검색하는 프록시 타입 public typealias DataFromURLCompletionClosure = (Data?) -> Void public struct ITunesProxy { public func sendGetRequest(searchTerm: String, _ handler: @escaping DataFromURLCompletionClosure) { let sessionConfiguration = URLSessionConfiguration.default var url = URLComponents() // url이 변경 되어도 여기서만 바꾸면 된다. url.scheme = "https" url.host = "itunes.apple.com" url.path = "/search" url.queryItems = [URLQueryItem(name: "term", value: searchTerm)] if let queryUrl = url.url { var request = URLRequest(url: queryUrl) request.httpMethod = "GET" let urlSession = URLSession(configuration: sessionConfiguration, delegate: nil, delegateQueue: nil) let sessionTask = urlSession.dataTask(with: request) { (data, response, error) in handler(data) } sessionTask.resume() } } } let proxy = ITunesProxy() proxy.sendGetRequest(searchTerm: "jimmy+buffett") { if let data = $0, let sString = String(data: data, encoding: String.Encoding(rawValue: String.Encoding.utf8.rawValue)) { print(sString) } else { print("Data is nil") } }
코드
참고 문헌
https://book.naver.com/bookdb/book_detail.nhn?bid=14107671
'POP' 카테고리의 다른 글
Swift4: Protocol Oriented Programming - 8.사례 연구 (0) 2021.03.06 Swift4: Protocol Oriented Programming - 7.스위프트에서 디자인 패턴 적용 - (3) 행위 패턴 (0) 2021.02.24 Swift4: Protocol Oriented Programming - 7.스위프트에서 디자인 패턴 적용 - (1) 생성 패턴 (0) 2021.02.19 Swift4: Protocol Oriented Programming - 6.프로토콜지향 프로그래밍 (0) 2021.02.17 Swift4: Protocol Oriented Programming - 5.객체지향 프로그래밍 (0) 2021.02.16 -