概述
描述
-
外部与一个子系统的通信必须通过一个统一的外观对象进行,为子系统中的一组接口提供一个一致的界面,外观模式定义了一个高层接口,这个接口使得这一子系统更加容易使用。外观模式又称为门面模式,它是一种对象结构型模式。
套路
-
外观角色 (Facade)
在客户端可以调用这个角色的方法,在外观角色中可以知道相关的子系统的功能和责任;在正常情况下,它将所有从客户端发来的请求委派到相应的子系统中去,传递给相应的子系统对象处理。 -
子系统角色(SubSystem)
在软件系统中可以有一个或者多个子系统角色,每一个子系统可以不是一个单独的类,而是一个类的集合,它实现子系统的功能;子系统并不知道外观(又称为门面)的存在,对于子系统而言,外观角色仅仅是另一个客户端而已。
使用场景
- 想要为访问一系列复杂的子系统提供一个统一的简单入口
- 客户端与多个子系统之间存在很大的依赖性,引入外观类可以将子系统和客户端解耦
- 在层次化结构中,可以使用外观模式定义系统中每一层的入口,层与层之间不直接产生联系
优缺点
- 优点
- 降低了客户类与子系统类的耦合度,实现了子系统与客户之间的松耦合关系
- 外观模式对客户屏蔽了子系统组件,从而简化了接口,减少了客户处理的对象数目并使子系统的使用更加简单。
- 降低原有系统的复杂度和系统中的编译依赖性,并简化了系统在不同平台之间的移植过程
- 缺点
- 在不引入抽象外观类的情况下,增加新的子系统可能需要修改外观类或客户端的源代码,违背了“开闭原则”
- 不能很好地限制客户使用子系统类,如果对客户访问子系统类做太多的限制则减少了可变性和灵活性。
UE4 实践
-
其实UE4有很多外观模式的影子,例如常调用的UKisme库t,很多都是集成封装好的,用户可以轻易调用
-
实现一个剧情过场的案例雏形
-
创建子系统角色类 —— 镜头序列轨道管理系统、特效管理系统、音频管理系统
UCLASS() // 镜头序列轨道管理系统 class DESIGNPATTERNS_API UCameraSubSystem : public UObject { GENERATED_BODY() public: void Play() { UE_LOG(LogTemp, Warning, TEXT(__FUNCTION__" Camera start moving.")); } void Stop() { UE_LOG(LogTemp, Warning, TEXT(__FUNCTION__" Camera stop moving.")); } }; UCLASS() // 特效管理系统 class DESIGNPATTERNS_API UVFXSubsystem : public UObject { GENERATED_BODY() public: void Play() { UE_LOG(LogTemp, Warning, TEXT(__FUNCTION__" VFX start playing.")); } void Stop() { UE_LOG(LogTemp, Warning, TEXT(__FUNCTION__" VFX stop playing.")); } }; UCLASS() // 音频管理系统 class DESIGNPATTERNS_API USFXSubsystem : public UObject { GENERATED_BODY() public: void Play() { UE_LOG(LogTemp, Warning, TEXT(__FUNCTION__" SFX start playing.")); } void Stop() { UE_LOG(LogTemp, Warning, TEXT(__FUNCTION__" SFX stop playing.")); } };
-
创建外观角色类
UCLASS() class DESIGNPATTERNS_API UFacadeObject : public UObject { GENERATED_BODY() public: UFacadeObject(){ CameraSubSystem = NewObject<UCameraSubSystem>(); VFXSubsystem = NewObject<UVFXSubsystem>(); SFXSubsystem = NewObject<USFXSubsystem>(); } ~UFacadeObject(){} // 开始过场剧场 void PlayCutscene() { CameraSubSystem->Play(); VFXSubsystem->Play(); SFXSubsystem->Play(); } // 结束过场剧场 void StopCutscene() { CameraSubSystem->Stop(); VFXSubsystem->Stop(); SFXSubsystem->Stop(); } private: UPROPERTY() UCameraSubSystem* CameraSubSystem; UPROPERTY() UVFXSubsystem* VFXSubsystem; UPROPERTY() USFXSubsystem* SFXSubsystem; };
-
调用测试
UCLASS() class DESIGNPATTERNS_API AFacadeTestActor : public AActor { GENERATED_BODY() public: AFacadeTestActor(); virtual void Tick(float DeltaTime) override; UPROPERTY() UFacadeObject* FacadeObject; protected: // Called when the game starts or when spawned virtual void BeginPlay() override { FacadeObject = NewObject<UFacadeObject>(); // 播放过场剧情 FacadeObject->PlayCutscene(); UE_LOG(LogTemp, Warning, TEXT(" ---------------------------------------------- ")); // 结束或跳过过场剧情 FacadeObject->StopCutscene(); } };
-
调式输出
LogTemp: Warning: UCameraSubSystem::Play Camera start moving. LogTemp: Warning: UVFXSubsystem::Play VFX start playing. LogTemp: Warning: USFXSubsystem::Play SFX start playing. LogTemp: Warning: ---------------------------------------------- LogTemp: Warning: UCameraSubSystem::Stop Camera stop moving. LogTemp: Warning: UVFXSubsystem::Stop VFX stop playing. LogTemp: Warning: USFXSubsystem::Stop SFX stop playing.