[디자인 패턴] Delegate Pattern

전성훈·2023년 10월 31일
0

DesignPattern

목록 보기
2/18

주제: 객체가 객체를 조작하는 방법


Delegate Pattern

  • Delegate Pattern은 소프트웨어 디자인 패턴 중 하나로, 객체 간의 커뮤니케이션을 도와주는 역할을 한다.
  • Delegate Pattern은 클래스나 구조체 간의 상호작용을 위해 일부 작업을 다른 객체에게 위임하는 방식으로 작동한다.
  • 이 패턴은 위임된 기능을 제공하기 위해 준수하는 타입이 보장되도록 위임된 책임을 캡슐화하는 프로토콜을 정의하여 구현한다.

Delegate Pattern의 활용 상황

  • 객체가 다른 객체에게 특정 작업을 위임하고자할 때
  • 객체 간의 결합도를 줄이고자 할 때
  • 이벤트 또는 사용자 상호작용에 대한 콜백을 제공하고자 할 때

Delegate pattern 수행 방법

  1. 프로토콜 정의
    • delegate pattern에서 protocol은 delegate가 수행해야 하는 메서드를 정의한다.
    • 이 프로토콜은 delegater(위임하는 객체)와 delegate(위임받는 객체)간의 계약을 설정한다.
  2. delegater 구현
    • delegater는 protocol에 정의된 메서드를 호출하여 delegate에게 작업을 위임한다.
    • delegater는 delegate protocol을 준수하는 옵셔널 프로퍼티를 통해 delegate를 가리킨다.
  3. delegate 구현
    • delegate protocol을 준수하고 delegate가 위임하는 작업을 수행할 책임이 있다.
    • delegate protocol에 정의된 메서드를 구현하여 delegater로부터 위임받은 작업을 처리한다.
  • 예를들어, UITableViewUITableViewDelegate를 사용하는 경우, UITableView는 델리게이터 역할을 하고, UITableViewDelegate 는 델리게이트 역할을 한다.
  • UITableViewDelegate 프로토콜에 정의된 메서드를 사용하여 사용자 상호작용 및 뷰 업데이트와 관련된 작업을 처리한다.

장단점

장점

  • 객체 간의 결합도를 줄여 가독성과 유지 관리가 쉬운 코드를 작성
  • 코드의 재사용성을 높여 다른 객체와 함께 쉽게 사용할 수 있다.
  • 객체 간의 역할 및 책임을 명확하게 구분하여 캡슐화를 향상시킨다.
  • 콜백 및 이벤트 처리를 위한 깔끔하고 일관된 방법을 제공한다.

단점

  • 프로토콜 및 델리게이트 구현이 코드의 복잡성을 증가시킬 수 있다.
  • 너무 많은 델리게이션은 코드 추적 및 디버깅이 어려울 수 있다.

MVP 구조를 통해서 Delegate pattern 예시

Delegate를 활용한 데이터 전송

protocol DataReceiverDelegate: AnyObject { 
	func didReceiveData(data: String)
}

class DataSender { 
	weak var delegate: DataReceiverDelegate?
	
	func sendData() { 
		let data = "Some data"
		
		delegate?.didReceiveData(data: data)
	}
}

class DataReceiver: DataReceiverDelegate { 
	let dataSender = DataSender()
	
	init() { 
		dataSender.delegate = self
		dataSender.sendData()
	}
	
	func didReceiveData(data: String) { 
		print("Data Receive: \(data)")
	}
}

delegater 구현 (ViewController)

final class ViewController: UIViewController { 
	private lazy var presenter = viewPresenter(viewController: self)
	
	override func viewDidLoad() { 
		super.viewDidLoad() 
		
		presenter.viewDidLoad() 
	}
}

extension ViewController: ViewProtocol { 
	func setupViews() { 
		// ... 
	}
	func setupLayout() { 
		// ...
	}
}

presenter에게 건낼 data를 포함한 model 구축

struct TestData { 
	let testData: String
}

protocol 및 delegate 구현 (ViewPresenter)

// protocol을 weak 처리하기 위한 조건 
protocol ViewProtocol: NSObject { 
	func setupViews()
	func setupLayout()
}

final class ViewPresenter { 
	private weak var viewController: ViewProtocol? 
	
	var testModel: TestData?
	
	init(
		viewController: ViewProtocol
	) {
		self.viewController = viewController
		self.testModel = TestModel(testData: "Test")
	 }
	
	 func viewDidLoad() { 
		 viewController?.setupViews()
		 viewController?.setupLayout()
	 }
}

결론

  • viewController에서 viewPresenter 객체를 할당해주면서, delegate을 할당해준다.
  • delegate에서 활용할 protocol에 메서드를 만들어주고, 그 protocol의 메서드를 viewController에서 구현해준다.
  • ViewPresenter에서 protocol을 할당받은 객체를 순환참조 방지를 위해 weak reference 할당 해주며, delegate에게 할당받은 메서드의 작동방식을 custom 해준다.

출처(참고문헌)

제가 학습한 내용을 요약하여 정리한 것입니다. 내용에 오류가 있을 수 있으며, 어떠한 피드백도 감사히 받겠습니다.

감사합니다.

0개의 댓글