目录
描述
套路
使用场景
优缺点
UE4实践
创建观察者抽象类
创建具体观察者类:工作人员
创建目标抽象类
创建目标具体类
定义对象之间的一种一对多依赖关系,使得每当一个对象状态发生改变时,其相关依赖对象都得到通知并更新。
观察者模式又称
不适用UE4中的委托代理,自己实现一个消息通知
做一个核辐射检测和救援人员受影响的例子
// 抽象观察者类
UCLASS(Abstract)
class DESIGNPATTERNS_API UObserver : public UObject
{
GENERATED_BODY()
public:
virtual void Update() PURE_VIRTUAL(UObserver::IsValid, );
};
// 具体观察者类 —— 工作人员
UCLASS(Blueprintable, BlueprintType)
class DESIGNPATTERNS_API UWorker : public UObserver
{
GENERATED_BODY()
public:
// 设置核辐射监测对象
void SetNuclearRadiation(UNuclearRadiation* pNuclearRadiation) {
m_pNuclearRadiation = pNuclearRadiation;
}
virtual void Update() override {
if (m_pNuclearRadiation)
{
int32 CurrentLevel = m_pNuclearRadiation->GetRadiationDegree();
if (CurrentLevel < 1)
{
UE_LOG(LogTemp, Warning, TEXT(__FUNCTION__" %s报告: 生命体征正常"), *this->GetName());
}
else if (CurrentLevel < 2)
{
UE_LOG(LogTemp, Warning, TEXT(__FUNCTION__" %s报告: 轻级损伤"), *this->GetName());
}
else if (CurrentLevel < 4)
{
UE_LOG(LogTemp, Warning, TEXT(__FUNCTION__" %s报告: 中级损伤"), *this->GetName());
}
else if (CurrentLevel < 6)
{
UE_LOG(LogTemp, Warning, TEXT(__FUNCTION__" %s报告: 重级损伤"), *this->GetName());
}
else if (CurrentLevel < 8)
{
UE_LOG(LogTemp, Warning, TEXT(__FUNCTION__" %s报告: 极重级损伤"), *this->GetName());
}
else
{
UE_LOG(LogTemp, Warning, TEXT(__FUNCTION__" %s已无生命体征"), *this->GetName());
this->ConditionalBeginDestroy();
// 不要在此处取消订阅,否则影响TArray遍历
}
}
}
private:
UNuclearRadiation* m_pNuclearRadiation;
};
// 抽象目标类
UCLASS(Abstract)
class DESIGNPATTERNS_API USubject : public UObject
{
GENERATED_BODY()
public:
// 添加订阅者
virtual void BindNotify(UObserver* Observer) {
if (!ObserverList.Contains(Observer)) {
ObserverList.Add(Observer);
UE_LOG(LogTemp, Warning, TEXT(__FUNCTION__" %s 已订阅"), *Observer->GetName());
// 第一次绑定 获取当前数据
Observer->Update();
}
}
// 移除订阅者
virtual void UnbindNotify(UObserver* Observer) {
if (ObserverList.Contains(Observer)) {
UE_LOG(LogTemp, Warning, TEXT(__FUNCTION__" %s 已取消订阅"), *Observer->GetName());
ObserverList.Remove(Observer);
}
}
// 通知
virtual void Notify() {
for (auto It = ObserverList.CreateConstIterator(); It; It++)
{
if (IsValid(*It))
{
(*It)->Update();
}
}
}
protected:
TArray ObserverList;
};
// 具体目标类 —— 辐射地带、辐射监测
UCLASS(Blueprintable, BlueprintType)
class DESIGNPATTERNS_API UNuclearRadiation : public USubject
{
GENERATED_BODY()
public:
// 更新辐射程度
void UpdateRadiationDegree(int32 pLevel) {
m_pLevel = pLevel;
Notify();
}
// 获取辐射程度
int32 GetRadiationDegree() {
return m_pLevel;
}
private:
// 辐射程度 1-9级
int32 m_pLevel;
};
测试
// 调用测试用的Actor
UCLASS()
class DESIGNPATTERNS_API AObserverActor : public AActor
{
GENERATED_BODY()
public:
void BeginPlay() override {
// 创建核辐射监测
UNuclearRadiation* NuclearRadiation = NewObject();
// 创建救援人员、监测核辐射程度
UWorker* Worker0 = NewObject();
Worker0->SetNuclearRadiation(NuclearRadiation);
NuclearRadiation->BindNotify(Worker0);
UWorker* Worker1 = NewObject();
Worker1->SetNuclearRadiation(NuclearRadiation);
NuclearRadiation->BindNotify(Worker1);
UWorker* Worker2 = NewObject();
Worker2->SetNuclearRadiation(NuclearRadiation);
NuclearRadiation->BindNotify(Worker2);
// 核辐射升级
NuclearRadiation->UpdateRadiationDegree(1);
NuclearRadiation->UpdateRadiationDegree(2);
NuclearRadiation->UpdateRadiationDegree(3);
// 有人先出来了,取消核辐射继续影响
NuclearRadiation->UnbindNotify(Worker2);
// 核辐射继续升级
NuclearRadiation->UpdateRadiationDegree(5);
NuclearRadiation->UpdateRadiationDegree(7);
NuclearRadiation->UpdateRadiationDegree(9);
GEngine->ForceGarbageCollection(true);
}
};
LogTemp: Warning: USubject::BindNotify Worker_0 已订阅
LogTemp: Warning: UWorker::Update Worker_0报告: 生命体征正常LogTemp: Warning: USubject::BindNotify Worker_1 已订阅
LogTemp: Warning: UWorker::Update Worker_1报告: 生命体征正常LogTemp: Warning: USubject::BindNotify Worker_2 已订阅
LogTemp: Warning: UWorker::Update Worker_2报告: 生命体征正常LogTemp: Warning: UWorker::Update Worker_0报告: 轻级损伤
LogTemp: Warning: UWorker::Update Worker_1报告: 轻级损伤
LogTemp: Warning: UWorker::Update Worker_2报告: 轻级损伤LogTemp: Warning: UWorker::Update Worker_0报告: 中级损伤
LogTemp: Warning: UWorker::Update Worker_1报告: 中级损伤
LogTemp: Warning: UWorker::Update Worker_2报告: 中级损伤LogTemp: Warning: UWorker::Update Worker_0报告: 中级损伤
LogTemp: Warning: UWorker::Update Worker_1报告: 中级损伤
LogTemp: Warning: UWorker::Update Worker_2报告: 中级损伤LogTemp: Warning: USubject::UnbindNotify Worker_2 已取消订阅
LogTemp: Warning: UWorker::Update Worker_0报告: 重级损伤
LogTemp: Warning: UWorker::Update Worker_1报告: 重级损伤LogTemp: Warning: UWorker::Update Worker_0报告: 极重级损伤
LogTemp: Warning: UWorker::Update Worker_1报告: 极重级损伤LogTemp: Warning: UWorker::Update Worker_0已无生命体征
LogTemp: Warning: UWorker::Update Worker_1已无生命体征