CS/DesignPattern

[DesignPattern] 이중버퍼

리네엔 2024. 10. 21. 22:06

Double Buffer Pattern이란?

  • 여러 순차 작업의 결과를 한번에 보여주기 위해 사용하는 패턴.
  • 그래픽스에서 주로 사용하지만, 그 외에도 사용할 곳이 있을 까?
    • 어떤 상태를 변경하는 코드가, 동시에 지금 변경하려는 상태를 읽는 경우. 물리나 인공지능 같이 객체가 서로 상호작용할 때 자주 발생

예시

그래픽스에 대한 예시는 너무 뻔하고 기본적으로 아는 내용이기 때문에 생략한다.
그래픽스가 아닌 다른 코드에서 사용할 수 있다는 점이 흥미로워 책의 내용을 남긴다.

  • 액터들이 돌아가면서 서로 때리는 장면을 보여주어야 한다고 가정.
  • 조건은 모든 배우가 한번에 업데이트 되는 것 처럼 보여야 한다면?
public class Actor
{
    public bool isSlaped {get;private set;} 
    public Actor face {get;set;}
    public void update() 
    {
        if(isSlaped)
        {
            face.slap();
        }
    }
    public void reset() {isSlaped = false;}
    public void slap() {isSlaped = true;}
    public Actor(Actor face)
    {
        this.face = face;
    }
}

public class Stage
{
    public void update()
    {
        for(int i = 0 ; i< NUM_ACTORS; i++)
        {
            actors[i].update();
            actors[i].reset();
        }
    }
    public void setActors()
    {
        Actor a = new Actor();
        Actor b = new Actor();
        Actor c = new Actor();
        a.face = b
        b.face = c
        c.face = a
        // 대충 a,b,c를 액터배열에 넣어주는 코드
    }

    public void anyOneFrame()
    {
        a.slap();
        update();
    }
}
  • 기대 출력

    a가 따귀를 맞았다. a는 b를 때린다.
    b가 따귀를 맞았다. b는 c를 때린다.
    c가 따귀를 맞았다. c는 a를 때린다.

이렇게 한 프레임 안에 전체 코미디언에게 전파되야 한다.

  • Actor의 순서를 바꾸면?
    public void setActors()
    {
        Actor a = new Actor();
        Actor b = new Actor();
        Actor c = new Actor();
        a.face = c
        b.face = a
        c.face = b
        // 대충 a,b,c를 액터배열에 넣어주는 코드
    }
  • 기대 출력

    a가 따귀를 맞았다. a는 아무것도 하지 않는다.
    b가 따귀를 맞았다. b는 아무것도 하지 않는다.
    c가 따귀를 맞았다. c는 a를 때린다.

배우의 맞은 상태를 바꿈과 동시에 같은 값을 읽기도 하니 업데이트 초반에 맞은 상태를 바꾼게 나중에 가서 영향을 미치게 됨.
배치 순서에 따라 이번프레임 내에 반응 할 수도, 다음 프레임에 반응 할 수도 있음.

이렇게 업데이트 순서에 따라 결과가 다르면 안될 때 이중버퍼 패턴을 사용할 수 있음.

public class Actor
{
    public bool currentSlapped{get;set;}
    public bool nextSlapped{get;set;}
    public void update() 
    {
        if(currentSlapped)
        {
            face.slap();
        }
    }
    pubilc void Swap()
    {
        // 버퍼 교체
        currentSlapped = nextSlapped;
        // 다음 버퍼 초기화
        nextSlapped = false;
    }
    public void slap() {nextSlapped = true;}
    public Actor(Actor face)
    {
        this.face = face;
    }
}
public class Stage
{
    public void update()
    {
        for(int i = 0 ; i< NUM_ACTORS; i++)
        {
            actors[i].update();
        }
                for(int i = 0 ; i< NUM_ACTORS; i++)
        {
            actors[i].Swap();
        }
    }
  • update()매서드는 모든 배우를 먼저 업데이트하고, 상태를 교체함.
  • actor객체는 자신이 맞았다는걸 다음 프레임에 알 수 있게되고, 배치순서와 상관없이 똑같이 행동하게 되었음.
  • 모든 배우가 한 프레임에 동시에 업데이트 되는 것으로 보이게 됨.

주의할 점은?

  • 버퍼를 교체할 방법.최대한 빠르게 교체해야한다. 버퍼 교체는 읽기와 쓰기 모두를 사용할 수 없게 한다.

'CS > DesignPattern' 카테고리의 다른 글

[DesignPattern] BuilderPattern  (0) 2024.10.25
[DesignPattern] 타입객체  (0) 2024.10.23
[DesignPattern] 프로토타입 패턴  (0) 2024.10.14
[DesignPattern] 경량 패턴  (0) 2024.10.14
[DesignPattern] 커맨드 패턴  (0) 2024.10.14