Notice
Recent Posts
Recent Comments
Link
관리 메뉴

김종권의 iOS 앱 개발 알아가기

[iOS - Swift] 4. 디자인 패턴 (구조 패턴) - 브릿지 패턴 (Bridge) 본문

Design Pattern (디자인 패턴)

[iOS - Swift] 4. 디자인 패턴 (구조 패턴) - 브릿지 패턴 (Bridge)

jake-kim 2023. 1. 1. 23:38

사전지식) 브릿지 패턴에서의 추상화와 구현 개념

  • 추상화: (=) 일부 개체​(entity)​에 대한 상위 수준의 제어 레이어
    • 이 레이어는 자체적으로 실제 작업을 수행하지 않고,  레이어​(구체클래스)에 위임

브릿지 패턴

  • 한 클래스안에 너무 많은 기능들과 여러 요소들이 있는 상태이고 이 클래스를 리팩토링 하고 싶은 경우? -> 브릿지 패턴 사용
  • 브릿지 패턴의 핵심은 추상화 레이어구현 레이어를 분리하는 것
  • 추상화 레이어는 기능을 수행하지 않고 기능에 대해서 필요한 경우 구현 레이어에 위임하고 구현 레이어의 메소드에 접근하여 사용

브릿지 패턴을 왜 쓰는가?

  • 하나의 클래스가 점점 커지면서 다양한 일들을 수행하게 된다면 복잡해지는 단점이 존재하는데 이 때 기능과 추상화를 나누기 위해 사용
  • 하나의 클래스를 추상화 레이어와 구현 레이어로 분리하여, 각각 독립적으로 구현할 수 있도록 해줄 수 있게 하기 위함
    • OCP: 추상화레이어와 기능레이어가 분리되어 있기 때문에 새로운 추상화와 구현들을 구현할 때 기존 코드를 수정하는 방향보단 추가하는 방향으로 가능
    • SRP: 추상화 레이어는 사용하는 쪽의 입장에만 관심이 있고, 구현 레이어는 오직 구현하는 내용에만 관심이 있는 형태

브릿지 패턴 예시

  • 브릿지 패턴 적용 전
    • RemoveControlOld라는것은 외부에서 필요로 하는 것들 volumnUp, volumnDown 인터페이스를 제공하는 동시에 내부에서 volumn을 컨트롤하는 기능도 제공
    • TV에대한 기능만 제공하므로, 나중에 라디오를 만들때 다 새로 만들어야하는 확장성이 낮은 코드
class RemoteControlTV {
    private var volumn = 0
    
    init() {
    }
    
    func volumnUp() {
        volumn += 1
    }
    func volumnDown() {
        volumn -= 1
    }
}
  • 브릿지 패턴 적용
    • 추상화 레이어 - RemoteControl 프로토콜
    • 구현 레이어 - Devicable
protocol Deviceable {
    func on()
    func volumnUp()
    func volumnDown()
    func channgelUp()
    func channgelDown()
}

class RemoteControl {
    private var device: Deviceable // bridge
    
    init(device: Deviceable) {
        self.device = device
    }
    
    func on() {
        device.on()
    }
    
    func volumnUp() {
        device.volumnUp()
    }
    
    func volumnDown() {
        device.volumnDown()
    }
    
    func channelUp() {
        device.channgelUp()
    }
    
    func channelDown() {
        device.channgelDown()
    }
}
  • 사용하는 쪽에서는 단순히 기능이 필요한 것들은 Deviceable을 준수하고, 이 인스턴스를 주입하여 사용
class TV: Deviceable {
    private var volumn = 0
    private var channel = 0
    
    func on() {
        print("turn on")
    }
    
    func volumnUp() {
        volumn -= 1
    }
    
    func volumnDown() {
        volumn -= 1
    }
    
    func channgelUp() {
        channel += 1
    }
    
    func channgelDown() {
        channel -= 1
    }
}

class ViewController: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
        
        let remoteControl = RemoteControl(device: TV())
        remoteControl.volumnUp()
    }
}
  • TV, Radio 등등 여러 가지의 확장성을 고려한 코드가 되었고, 추상화를 담당하는 RemoteControl과 기능을 담당하는 Deviceable는 각각 하나의 액터에 대해서만 책임지므로 SRP원칙을 준수
    • 복잡한 하나의 클래스를 리팩토링해보자 -> 브릿지 패턴을 사용하여 추상화 레이어와 기능 레이어를 분리하자

* 전체 코드: https://github.com/JK0369/ExBridgePattern

* 참고

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

Comments