cozzin
코찐 기술 블로그
cozzin
전체 방문자
오늘
어제
  • 분류 전체보기
    • Kotlin
    • 백엔드
    • iOS
      • Swift
      • SwiftUI
      • Combine
      • Architecture
    • 개발환경
    • 세미나
    • 생각정리
    • 스터디
    • CS
      • Refactoring
      • OS

블로그 메뉴

  • 홈
  • 태그
  • 방명록
  • LinkedIn
  • 강의

공지사항

인기 글

태그

  • 디자인패턴
  • multicast
  • 운영체제
  • Swift
  • 컴퓨터공학
  • 리팩토링
  • Ribs
  • slide-over
  • XCode
  • CS
  • os
  • 워닝제거
  • WWDC
  • Combine
  • Warning
  • SwiftUI
  • WWDC21
  • ios
  • 테스트
  • darkmode

최근 댓글

최근 글

티스토리

hELLO · Designed By 정상우.
cozzin

코찐 기술 블로그

[디자인패턴] 전광판을 예시로 풀어본 Bridge 패턴
스터디

[디자인패턴] 전광판을 예시로 풀어본 Bridge 패턴

2021. 5. 24. 10:05
반응형

안녕하세요 홍성호 입니다.

요즘 Java 언어로 배우는 디자인 패턴 입문 책으로 사내 스터디에 참여중 입니다.

https://book.naver.com/bookdb/book_detail.nhn?bid=4529127 

 

JAVA 언어로 배우는 디자인 패턴 입문

JAVA 언어를 통해 알기 쉽게 배우는 디자인 패턴!『JAVA 언어로 배우는 디자인 패턴 입문』은 디자인 패턴의 기초를 소개하는 입문서이다. 디자인 패턴은 먼 장래를 위해 배우는 것이 아니다. 우리

book.naver.com

 

평소에도 발표한다고 생각하고 스터디를 준비했었지만, 이번에는 진짜 발표를 하는거라 더 신경쓰이네요.

여러 각도에서 패턴을 살펴보겠습니다.

 

Bridge 패턴

'기능의 클래스 계층'과 '구현의 클래스 계층' 사이에 다리를 놓는 패턴이라고 소개되고 있습니다.

이 정의가 무슨말인지 한번에 이해가 되지 않았습니다 😭😭😭

제가 지식이 부족해서 그럴 수도 있지만, 책의 정의가 직관적이지 않다고 생각합니다.

이 글을 쓰면서 좀 더 좋은 정의를 찾아보겠습니다.

 

풀고싶은 문제

책의 예제를 조금 응용해서 전광판을 한번 만들어보겠습니다.

 

https://www.isign.co.kr/?p=4333

 

요구사항 1: 다양한 화면에서 보여주고 싶어요

이 전광판은 흑백 디스플레이에서 보여줄 수 있고, 컬러 디스플레이에서도 작동할 수 있으면 좋겠습니다.  

더 나아가 미래의 어떤 장치로도 출력 가능하도록 만들고 싶습니다.

점자 디스플레이가 될 수도 있고, 3D 디스플레이가 될 수도 있겠네요.

 

요구사항 2: 깜빡 거리는 기능을 추가하고 싶어요

사람들의 눈에 띄도록 깜빡 거리는 전광판도 있으면 좋겠어요.

물론 흑백, 컬러 다 지원되어야 하죠.

 

해결책

글자를 보여줄 화면의 종류는 무한대로 늘어날 수도 있습니다.

화면을 추가할 때마다 정해진 틀 없이 코드를 작성 한다면 유지보수하기 너무 어려울 것 입니다.

 

이것을 해결하기 위해서 화면을 추상화 해보겠습니다.

프로토콜이나 추상 클래스로 추상화할 수 있습니다.

추상화된 틀을 가진 조작 기기는 여러 객체로 교체 가능합니다!

 

그러면 깜빡 거리는 기능을 추가하는 요구사항은 어떻게 해결할까요?

깜빡 거리는 기능을 추가하는 것은 무한대로 늘어나는 것은 아니며 기존 기능을 살려서 추가 구현할 계획입니다.

전광판 객체를 상속받아서 구현할 계획입니다.

 

상속 받아서 구현한다면

브릿지 패턴 사용해서 구현한다면

 

코드로 구현해보기

디스플레이를 추상화한 프로토콜 입니다.

protocol Display {
    func on()
    func off()
}

 

흑백으로 글자를 표시하는 디스플레이 입니다.

 

final class GrayScaleDisplay: Display {
    
    private let text: String
    private let label: UILabel
    
    init(text: String, label: UILabel) {
        self.text = text
        self.label = label
    }
    
    func on() {
        label.attributedText = NSAttributedString(string: text, attributes: [
            .font: UIFont.boldSystemFont(ofSize: 30),
            .foregroundColor: UIColor.systemGray
        ])
    }
    
    func off() {
        label.attributedText = NSAttributedString(string: text.map { _ in "." }.joined(), attributes: [
            .font: UIFont.boldSystemFont(ofSize: 30),
            .foregroundColor: UIColor.black
        ])
    }
}

 

랜덤 컬러로 글자를 표시하는 디스플레이 입니다.

 

final class ColorDisplay: Display {
    
    private let text: String
    private let label: UILabel
    
    init(text: String, label: UILabel) {
        self.text = text
        self.label = label
    }
    
    func on() {
        label.attributedText = NSAttributedString(string: text, attributes: [
            .font: UIFont.boldSystemFont(ofSize: 30),
            .foregroundColor: UIColor(
                red: .random(in: 0...1),
                green: .random(in: 0...1),
                blue: .random(in: 0...1),
                alpha: 1.0
            )
        ])
    }
    
    func off() {
        label.attributedText = NSAttributedString(string: text.map { _ in "." }.joined(), attributes: [
            .font: UIFont.boldSystemFont(ofSize: 30),
            .foregroundColor: UIColor.black
        ])
    }
}

 

전광판 로직을 객체로 만들었습니다.

Display 객체를 받아서 단순히 on/off 만 실행하고 있습니다.

 

class PlainAD {
    
    private let display: Display
    
    init(display: Display) {
        self.display = display
    }
    
    func start() {
        display.on()
    }
    
    func end() {
        display.off()
    }
}

 

깜빡거리는 기능이 추가된 전광판 입니다.

타이머를 포함하고 있어서 일정 시간 반복하며 깜빡거립니다.

 

final class FlickerAD: PlainAD {
    
    private var timer: DispatchSourceTimer?
    
    func startFlicker() {
        timer = DispatchSource.makeTimerSource(queue: .global())
        timer?.schedule(deadline: .now(), repeating: .seconds(1))
        
        var isOn: Bool = false
        timer?.setEventHandler(handler: { [weak self] in
            DispatchQueue.main.async {
                if isOn {
                    self?.end()
                } else {
                    self?.start()
                }
                isOn.toggle()
            }
        })
        timer?.resume()
    }
    
    func endFlicker() {
        timer?.cancel()
        timer = nil
        end()
    }
}

 

실행하는 부분은 다음과 같습니다.

 

@objc
private func didTouchStartButton() {
    plainGrayAD.start()
    plainColorAD.start()
    flickerGrayAD.startFlicker()
    flickerColorAD.startFlicker()
}

@objc
private func didTouchEndButton() {
    plainGrayAD.end()
    plainColorAD.end()
    flickerGrayAD.endFlicker()
    flickerColorAD.endFlicker()
}

 

요구사항대로 잘 실행됩니다!!

 

https://github.com/cozzin/DesignPattern/tree/main/DesignPattern/Bridge

 

cozzin/DesignPattern

디자인 패턴 스위프트로 구현하기. Contribute to cozzin/DesignPattern development by creating an account on GitHub.

github.com

 

용어 정리

기능의 클래스 계층

함수안에 어떤 동작을 하면 기능하는 것이라고 볼 수 있을텐데 너무 범용적인 말이라고 생각합니다ㅠ

예제에서는 기본 절차를 구현해두고 추가적인 절차가 있을 때 객체를 상속 받아서 구현하고 있습니다.

기본 절차 및 추가적인 절차 구현 이라고 볼 수 있습니다.

부모 객체에 강한 종속을 갖기 때문에 확장은 제한적 입니다.

 

구현의 클래스 계층

구현이라는 말도 애매한데요.

위에서 본 예제의 Display가 속해 있는 계층이 이곳입니다.

정해진 틀을 지키면 무한대로 확장이 일어날 수 있는 것을 이 계층에 담습니다.

추상화 가능한 것을 나눈 계층 이라고 볼 수 있습니다.

 

생각 정리

  • 정의를 좀 더 잘 해보고 싶었는데 여전히 복잡한 것 같습니다...
  • 이해 못한 것: 왜 구현의 클래스 계층이라고 정의했는지 잘모르겠음
  • 장점으로 생각되는 것: 상속할 부분과 위임할 부분을 구분해서 사용할 수 있습니다.
  • 단점으로 생각되는 것: 두 계층 사이의 Mediator 객체가 따로 있는게 아니라서 브릿지라는 메타포가 쉽게 떠오르지 않습니다ㅠ

 

토론 거리

  • iOS에 브릿지패턴이 적용된게 있을지
    • iOS 프레임워크 자체에 적용된건 떠오르는게 없음
    • 공유하기 기능에 적용한 예제: https://refactoring.guru/design-patterns/bridge/swift/example#example-1
  • 사용해본 경험이 있는지
  • 또 어디에 적용하면 좋을지
    • 멀티플랫폼 지원하는 소프트웨어: 다양한 플랫폼을 추상화해서 사용
    • 게임: 키보드, 조이스틱, 터치스크린 등으로 조작 가능한 게임 만들 때

 

참고

https://blog.naver.com/doyoung0205/221761552596

https://book.naver.com/bookdb/book_detail.nhn?bid=4529127

https://joycestudios.tistory.com/38

 

더보기
브릿지패턴.key
0.48MB
반응형
저작자표시 (새창열림)

'스터디' 카테고리의 다른 글

[엘레강트 오브젝트] '생성자에 코드를 넣지 마세요' 적용해보기  (0) 2021.05.19
[디자인패턴] Builder 패턴  (1) 2021.05.18
[디자인패턴] Template Method 패턴  (1) 2021.05.05
[디자인패턴] Iterator 패턴을 Swift로 구현해보기  (0) 2021.05.03
    '스터디' 카테고리의 다른 글
    • [엘레강트 오브젝트] '생성자에 코드를 넣지 마세요' 적용해보기
    • [디자인패턴] Builder 패턴
    • [디자인패턴] Template Method 패턴
    • [디자인패턴] Iterator 패턴을 Swift로 구현해보기
    cozzin
    cozzin
    Software Engineer

    티스토리툴바