【UE4 设计模式】外观模式 Facade Pattern

概述

描述

  • 外部与一个子系统的通信必须通过一个统一的外观对象进行,为子系统中的一组接口提供一个一致的界面,外观模式定义了一个高层接口,这个接口使得这一子系统更加容易使用。外观模式又称为门面模式,它是一种对象结构型模式。

    image

套路

  • 外观角色 (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.
    

参考

posted @ 2021-06-20 10:51  砥才人  阅读(339)  评论(0编辑  收藏  举报