Humility

아무리 노력해도 최고가 되지 못할 수 있다⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀그럼에도 노력하는자가 가장 겸손한 것 아닌가

공부하는 블로그

유니티/디자인패턴

[Unity] 유니티 C#) Facade 패턴

새벽_글쓴이 2024. 12. 16. 10:28
반응형

파사드 패턴

복잡한 시스템을 간단한 인터페이스로 제공하는 구조적 디자인 패턴

 

기본 구현 방법

1. 복잡한 하위 시스템들

public class AudioSystem
{
    public void InitializeAudio() => Debug.Log("오디오 시스템 초기화");
    public void PlayBackgroundMusic() => Debug.Log("배경음악 재생");
    public void PlaySoundEffect(string effect) => Debug.Log($"효과음 재생: {effect}");
}

public class SaveSystem
{
    public void SaveGameState() => Debug.Log("게임 상태 저장");
    public void LoadGameState() => Debug.Log("게임 상태 불러오기");
}

public class EnemySpawner
{
    public void InitializeSpawner() => Debug.Log("스포너 초기화");
    public void StartSpawning() => Debug.Log("적 생성 시작");
    public void StopSpawning() => Debug.Log("적 생성 중지");
}

public class UIManager
{
    public void InitializeUI() => Debug.Log("UI 초기화");
    public void ShowMainMenu() => Debug.Log("메인 메뉴 표시");
    public void ShowGameUI() => Debug.Log("게임 UI 표시");
}

 

2. Facade 클래스

public class GameManager
{
    private AudioSystem audioSystem;
    private SaveSystem saveSystem;
    private EnemySpawner enemySpawner;
    private UIManager uiManager;

    public GameManager()
    {
        audioSystem = new AudioSystem();
        saveSystem = new SaveSystem();
        enemySpawner = new EnemySpawner();
        uiManager = new UIManager();
    }

    // 간단한 인터페이스 제공
    public void StartGame()
    {
        Debug.Log("게임 시작 절차 시작");
        audioSystem.InitializeAudio();
        audioSystem.PlayBackgroundMusic();
        
        enemySpawner.InitializeSpawner();
        enemySpawner.StartSpawning();
        
        uiManager.InitializeUI();
        uiManager.ShowGameUI();
        
        saveSystem.LoadGameState();
    }

    public void PauseGame()
    {
        Debug.Log("게임 일시정지");
        enemySpawner.StopSpawning();
        saveSystem.SaveGameState();
        uiManager.ShowMainMenu();
    }

    public void ResumeGame()
    {
        Debug.Log("게임 재개");
        enemySpawner.StartSpawning();
        uiManager.ShowGameUI();
        audioSystem.PlayBackgroundMusic();
    }
}

 

3.사용 예시

public class GameController : MonoBehaviour
{
    private GameManager gameManager;

    void Start()
    {
        gameManager = new GameManager();
        
        // 복잡한 시스템들을 간단한 인터페이스로 사용
        gameManager.StartGame();
    }

    void Update()
    {
        if (Input.GetKeyDown(KeyCode.P))
        {
            gameManager.PauseGame();
        }
        else if (Input.GetKeyDown(KeyCode.R))
        {
            gameManager.ResumeGame();
        }
    }
}

 

핵심 개념

  • 복잡한 하위 시스템들을 간단한 통합 인터페이스로 제공
  • 서브시스템의 복잡성을 감추고 간단한 진입점 제공
  • 시스템 간의 강한 결합도를 낮춤
  • "단순한 창구" 역할을 하는 패턴

 

사용 목적

  • 복잡한 시스템을 쉽게 사용하기 위해
  • 서브시스템 간의 결합도 감소
  • 클라이언트 코드 단순화
  • 시스템 사용의 진입장벽 낮춤
  • 통일된 인터페이스 제공

 

사용사례 및 예시코드

게임 상태 관리

public class GameStateFacade 
{
    private SaveSystem saveSystem;
    private LevelLoader levelLoader;
    private PlayerStats playerStats;

    public void SaveGameState() 
    {
        playerStats.PrepareForSave();
        saveSystem.SaveGame();
        levelLoader.SaveCurrentState();
    }

    public void LoadGameState() 
    {
        saveSystem.LoadGame();
        levelLoader.LoadSavedState();
        playerStats.RestoreFromSave();
    }
}

 

리소스 로딩 시스템

public class ResourceLoaderFacade 
{
    private AudioLoader audioLoader;
    private TextureLoader textureLoader;
    private ModelLoader modelLoader;

    public async Task LoadLevelResources(string levelName) 
    {
        await audioLoader.LoadAudioFiles(levelName);
        await textureLoader.LoadTextures(levelName);
        await modelLoader.LoadModels(levelName);
    }
}

 

UI관리 시스템

public class UIFacade 
{
    private MenuPanel menuPanel;
    private InventoryUI inventoryUI;
    private HUDSystem hudSystem;

    public void ShowGameplayUI() 
    {
        menuPanel.Hide();
        inventoryUI.Initialize();
        hudSystem.Show();
    }

    public void ShowMainMenu() 
    {
        hudSystem.Hide();
        inventoryUI.Hide();
        menuPanel.Show();
    }
}

 

오디오 시스템

public class AudioFacade 
{
    private BGMPlayer bgmPlayer;
    private SFXPlayer sfxPlayer;
    private AudioMixer audioMixer;

    public void PlayGameplayAudio() 
    {
        bgmPlayer.PlayGameBGM();
        sfxPlayer.LoadGameSFX();
        audioMixer.SetGameplayMix();
    }

    public void PlayMenuAudio() 
    {
        bgmPlayer.PlayMenuBGM();
        sfxPlayer.LoadMenuSFX();
        audioMixer.SetMenuMix();
    }
}

 

결론

장점

  • 복잡한 시스템 사용이 간단해짐
  • 코드 가독성과 유지보수성 향상
  • 시스템 간 결합도 감소
  • 일관된 인터페이스 제공

 

주의사항

  • Facade 클래스가 너무 많은 책임을 가지지 않도록 주의
  • 모든 시스템을 Facade로 만들 필요는 없음
  • 적절한 추상화 수준 유지 필요

 

유용한 상황

  • 여러 시스템이 결합된 복잡한 게임 기능 구현
  • 다수의 컴포넌트를 조작해야 하는 경우
  • 시스템 초기화나 상태 변경이 복잡한 경우
  • 재사용 가능한 시스템을 만들어야 할 때

 

게임 개발에서 복잡한 시스템들을 효과적으로 관리하고
사용하기 쉽게 만들어주는 매우 유용한 디자인 패턴인 것 같다
반응형