C++|관찰자 패턴

관찰자 모드:

객체(주체)의 상태가 변경되면 이에 의존하는 모든 객체가 알림을 받고 자동으로 업데이트되도록 객체 간의 일대다(변경) 종속 관계를 정의합니다.

동기 부여:

소프트웨어 구성 프로세스 중에 특정 개체에 대한 "알림 종속성"을 설정해야 합니다. 즉, 한 개체(대상 개체)의 상태가 변경되면 모든 종속 개체(관찰자 개체)에 알림이 전달됩니다. 이러한 종속성이 너무 엄격하면 소프트웨어가 변경 사항을 잘 견딜 수 없습니다.

객체지향 기술을 사용하면 이러한 종속성을 약화시켜 안정적인 종속성을 형성할 수 있습니다. 소프트웨어 아키텍처의 느슨한 결합을 달성하기 위해

요약하다:

  • 객체 지향 추상화를 사용하면 관찰자 패턴을 사용하여 대상과 관찰자를 독립적으로 변경할 수 있으므로 둘 사이의 종속성을 느슨하게 결합할 수 있습니다.
  • 대상이 알림을 보낼 때 관찰자를 지정할 필요가 없으며 알림(알림 정보를 매개변수로 전달할 수 있음)이 자동으로 전파됩니다.
  • 관찰자는 알림을 구독할지 여부를 결정하고 대상 개체는 이에 대해 아무것도 모릅니다.
  • Observer 패턴은 이벤트 기반 UI 프레임워크에서 매우 일반적으로 사용되는 디자인 패턴이자 MVC 패턴의 중요한 부분입니다.

실제 사례

기존 비즈니스 시나리오가 있는 경우 비디오 감지기를 작성해야 합니다. 감지기는 이미지 분할 모델을 사용하여 입력 비디오 스트림을 감지합니다. 사진에 사람이 있는 것으로 감지되면 사람에 대한 특정 작업이 필요합니다. (예: 사람을 잘라내는 등 사람들을 프레임으로 분할하는 등), 화면에서 자동차를 감지하면 특정 작업(예: 자동차를 빨간색으로 칠하는 등)도 수행합니다.
이러한 비즈니스 시나리오를 작성하는 일반적인 방법에서는 비디오 스트림을 읽고, 이미지의 각 프레임을 감지한 다음, if else
if 사람이 감지되면 작성하는 것을 쉽게 생각할 수 있습니다. {…}
else if 자동차가 감지되면 {…}
else if the sky isDetected {...}
이 구현 방법은 요구 사항을 충족할 수 있지만 설계 원칙을 충족하지 않습니다
. 이는 긴밀하게 결합된 접근 방식입니다. 감지기는 다른 비디오 작업 클래스에 의존합니다. 종속성을 준수하지 않는 경우 반전 원리를
사용하면 작업 클래스가 인터페이스로 추상화되고 작업이 필요할 때 인터페이스가 호출됩니다. 이렇게 하면 문제가 해결됩니다.
하지만 또 다른 점이 있습니다. 이 비즈니스 시나리오에서는 작업 클래스에 다른 작업이 있으므로 여러 작업이 필요합니다.
더 추상화하기 때문에
작업 기본 클래스를 작성한 다음 여러 작업 클래스를 작성합니다. 1 , 오퍼레이션 클래스 2는 모두 기본 클래스를 상속하는데
, 이 단계에서 실제로 관찰자 모델이 나옵니다.

관찰자 모델:
영상을 관찰된 사람으로 간주할 수 있으며, 감지된 결과(사람, 자동차, 나무 등)는 정보 알림과 동일합니다.누가 알림을 받아야 합니까? 특정 작업 클래스를 알리면 사람을 대상으로 작업하는 클래스와 자동차를 작업하는 클래스를 관찰자로 간주할 수 있습니다.
관찰자는 관찰자에게 메시지를 보내고, 관찰자는 메시지를 기반으로 다양한 연산(다형성)을 수행하며,
이 과정에서 관찰자는 메시지 구독 여부를 선택할 수 있도록 지원됩니다.
여기에 이미지 설명을 삽입하세요.

코드 구현 및 설명:

#include <string>
#include <iostream>
#include <list>
using namespace std;


class Observer {
    
    // 抽象类(接口)
public:
	virtual void handleVideo(string detectInfo) = 0;
	virtual ~Observer() {
    
    }
};

class Observer1 : public Observer {
    
    
public:
	virtual void handleVideo(string detectInfo) {
    
    
		cout << "截取人" << endl;
	}
};

class Observer2 : public Observer {
    
    
public:
	virtual void handleVideo(string detectInfo) {
    
    
		cout << "截取汽车" << endl;
	}
};

class VideoDetecter {
    
    
	string m_filePath;
	string m_fileName;
	list<Observer*>  m_observerList; // 抽象通知机制,支持多个观察者

public:
	VideoDetecter(string filePath, string fileName) {
    
    
		m_filePath = filePath;
		m_fileName = fileName;
	}
	void detect() {
    
    
		//1.读取视频流
		cout << "读取视频流:" << m_filePath + m_fileName << endl;
		//2.循环每一帧处理
		int frameNum = 10;
		for (int i = 0; i < frameNum; i++) {
    
    
			//假设对第i帧图像处理得到识别结果 结果记作 detectInfo
			string detectInfo = "识别结果";
			sendNotify(detectInfo);//发送通知
		}
	}
	void addObserver(Observer* observer) {
    
     //添加观察者
		m_observerList.push_back(observer);
	}
	void removeObserver(Observer* observer) {
    
     //移除观察者
		m_observerList.remove(observer);
	}
protected:
	virtual void sendNotify(string detectInfo) {
    
    
		list<Observer*>::iterator itor = m_observerList.begin();
		while (itor != m_observerList.end()) {
    
    
			(*itor)->handleVideo(detectInfo); //不同观察者对通知做出响应
			itor++;
		}
	}
};

int main() {
    
    
	string filePath = "/root/home/videoPath/";
	string fileName = "001.mp4";
	Observer* observer;

	VideoDetecter detecter(filePath, fileName);
	Observer1 ob1;
	Observer2 ob2;
	detecter.addObserver(&ob1);
	detecter.addObserver(&ob2);
	detecter.detect();
	detecter.removeObserver(&ob1);
	detecter.removeObserver(&ob2);
	//detecter.detect();

}

추천

출처blog.csdn.net/holly_Z_P_F/article/details/132523906