Delphi의 Observer 패턴은 기본 Observer 패턴을 확장합니다. 관찰자 모드에 대한 자세한 내용은 [Gam+, 293..303페이지]를 참조하세요.
개체 간의 일대다 종속 관계를 정의합니다. 개체의 상태가 변경되면 해당 개체에 종속된 모든 개체에 알림이 전달되고 자동으로 업데이트됩니다.
시스템을 일련의 협력 클래스로 분할하면 특정 부작용이 있습니다. 즉, 관련 개체 간의 일관성을 보호해야 합니다. 차원 일관성을 위해 유형을 긴밀하게 결합하고 싶지 않습니다. 이렇게 하면 재사용성이 떨어지기 때문입니다. [감+,p293].
Delphi의 이벤트(실제 메소드 주소)를 사용하면 이러한 문제를 처리하기 위한 좋은 구조를 가질 수 있습니다. 이벤트를 사용하면 결합을 제거하고 더 나은 결합을 달성할 수 있습니다. 예를 들어 TButton.OnClick 이벤트가 관련 작업을 완료하기 위해 전달됩니다. 그러나 클래스는 이벤트 핸들러에 대한 참조를 저장하지 않습니다. 관찰자 패턴에서는 이벤트를 전달하는 클래스를 대상 객체(주체)라고 하고, 이벤트를 제어하는 클래스를 관찰자(관찰자)라고 합니다.
Delphi의 이벤트는 클래스 결합을 더 잘 제거할 수 있습니다. 여러 이벤트를 제어하고 관찰자 모드를 참조하려는 경우 일대다 알림 메커니즘을 설정할 수 있습니다. 대상에는 원하는 수의 관찰자가 있을 수 있습니다. 모든 관찰자는 대상의 상태가 변경되면 알림을 받습니다. 관찰자는 알림을 받은 후 즉시 대상 개체에 쿼리하여 대상 개체와의 동기화를 유지합니다.
이 상호 작용을 게시-구독이라고도 하며 대상은 알림 게시자입니다. 알림을 발견할 때 관찰자가 누구인지 알 필요가 없습니다. 관찰자는 원하는 수만큼 구독하고 알림을 받을 수 있습니다.
이 관찰자 모드 애플리케이션은 클래스 결합 처리에 있어 Delphi 이벤트 메커니즘의 이점을 제공합니다. 일대다 구조는 등록 및 등록 취소를 통해 관찰자를 등록합니다. 일대다 메커니즘은 실제로 반복자를 기반으로 적용됩니다.
의미 있는 동작을 정의하는 Tsubject 클래스가 있다고 가정합니다. 먼저 관찰자 모드의 데모 코드를 살펴보겠습니다.
유형
TSubject = 클래스(TObject)
사적인
FObserver: TList;
공공의
절차 RegisterObserver(관찰자: TSubjectObserver);
절차 UnregisterObserver(관찰자: TSubjectObserver);
끝;
TSubjectObserver = 클래스(TComponent)
사적인
FEnabled: 부울;
출판됨
속성 활성화: 부울 읽기 FEnabled 쓰기 FEnabled 기본값 True;
끝;
위의 인터페이스 중:
? Tsubject에 대한 관찰자를 등록하기 위한 등록 메커니즘입니다.
¨ FObservers: TList는 등록된 관찰자를 저장합니다.
¨ RegisterObserver(..)는 관찰자를 등록하고 Fobserver에 추가하는 데 사용됩니다.
¨ UnregisterObserver(..)는 관찰자의 등록을 취소하고 Fobserver에서 관련 개체를 제거하는 데 사용됩니다.
?관찰자 모드에서는 새로운 클래스 TsubjectObserver도 생성해야 합니다.
¨ 이 클래스는 TcomComponent의 자손입니다.
¨ .Enabled 속성은 관찰을 켜거나 끕니다. .
다음 관찰자 모드의 실제 적용:
절차 TSubject.RegisterObserver(Observer: TSubjectObserver);
시작하다
FObservers.IndexOf(Observer) = -1이면
FObservers.Add(관찰자);
끝;
절차 TSubject.UnregisterObserver(Observer: TSubjectObserver);
시작하다
FObservers.Remove(관찰자);
끝;
Shangguan의 구현은 관찰자의 등록 부분을 지원합니다. 일대다 알림 메커니즘은 어디에 있나요? 실제 일대다 알림 응용 프로그램의 경우 Tsubject에 대한 Change 메서드를 정의하여 등록된 관찰자에게 알리고 관찰자는 일정을 처리하기 위해 OnChange 이벤트 속성을 정의할 수 있습니다. 코드는 다음과 같습니다:
유형
TSubject = 클래스(TObject)
사적인
FObserver: TList;
보호됨
» 프로시저 변경 {알림을 전달하려면 이 메소드를 호출하십시오.}
공공의
절차 RegisterObserver(관찰자: TSubjectObserver);
절차 UnregisterObserver(관찰자: TSubjectObserver);
끝;
TSubjectObserver = 클래스(TComponent)
사적인
FEnabled: 부울;
» FOnChange: TNotifyEvent;
보호됨
» 절차 변경;
출판됨
속성 활성화: 부울 읽기 FEnabled 쓰기 FEnabled;
» 속성 OnChange: TNotifyEvent 읽기 FOnChange 쓰기 FOnChange;
끝;
구현
절차TSubject.Change;
var
» 관찰: TSubjectObserver;
» I: 정수;
시작하다
» for I := 0 ~ FObservers.Count - 1 do
" 시작하다
» 관찰자 := FObservers[I];
» Obs.Enabled이면 Obs.Change입니다.
" 끝;
끝;
절차 TSubject.RegisterObserver(Observer: TSubjectObserver);
시작하다
FObservers.IndexOf(Observer) = -1이면
FObservers.Add(관찰자);
끝;
절차 TSubject.UnregisterObserver(Observer: TSubjectObserver);
시작하다
FObservers.Remove(관찰자);
끝;
절차TSubjectObserver.Change;
시작하다
» 할당된 경우(FOnChange) 그러면 FOnChange(Self);
끝;
위의 구현 코드에서:
? Tsubject의 Change 메서드는 등록된 모든 관찰자를 통해 반복하고 일대다 알림 구현인 각 관찰자의 Change 메서드를 호출합니다.
? 관찰자의 Enabled 속성은 알림을 받거나 받는지 여부를 결정합니다.
? TsubjectObserver의 OnChange 이벤트는 실제로 동기화 및 기타 작업을 처리합니다.
정리
//"디자인 패턴"에서 많은 부분 발췌