UndoRedoStack

๊ฐœ์š”

UndoRedoStack์€ ์‹คํ–‰ ์ทจ์†Œ์™€ ๋‹ค์‹œ ์‹คํ–‰์„ ํ•˜๊ธฐ ์œ„ํ•ด ๊ตฌํ˜„ํ•œ ๋””์ž์ธ ํŒจํ„ด์ด์—์š”.

๋‹ค์–‘ํ•œ ์†Œํ”„ํŠธ์›จ์–ด์—์„œ ๊ฐ์ž์˜ ๋ฐฉ๋ฒ•์œผ๋กœ ๊ตฌํ˜„ ๋˜์–ด ์žˆ์ง€๋งŒ, ์ €๋Š” ์กฐ๊ธˆ ๊ฐ„๋‹จํ•˜๊ฒŒ ํ•„์š”ํ•œ ๊ธฐ๋Šฅ๋งŒ ๊ตฌํ˜„ํ•˜์—ฌ ๊ฐ ๊ธฐ๋Šฅ๋“ค์„ ์•ก์…˜(Action)์œผ๋กœ ๋‚˜๋ˆ„์–ด ๋ณด์•˜์–ด์š”.

๊ทธ๋ฆฌ๊ณ  ๊ฐ Action์„ ๋ฌถ์€ ActionBlock ํด๋ž˜์Šค๋ฅผ ๋งŒ๋“ค์–ด Sequence๋ฅผ ๊ตฌํ˜„ํ•˜๋„๋ก ํ–ˆ์–ด์š”.

์ด๋ฅผ ํ†ตํ•ด ๋ณต์žกํ•œ Undo ๋˜๋Š” Redo ์ž‘์—…์„ ํ•œ๋ฒˆ์— ์ฒ˜๋ฆฌ ํ•  ์ˆ˜ ์žˆ์–ด์š”.

IUndoableAction

public interface IUndoableAction
{
    void Do();
    void Undo();
}

ActionBlock

public class ActionBlock : IUndoableAction
{
    private readonly IUndoableAction[] actionSequence;

    public ActionBlock(params IUndoableAction[] actionSequence)
    {
        this.actionSequence = actionSequence;
    }

    public void Do()
    {
        foreach (var action in actionSequence)
            action.Do();
    }

    public void Undo()
    {
        foreach (var action in actionSequence.Reverse())
            action.Undo();
    }

    public override string ToString()
    {
        return string.Join(",", actionSequence.Select(a => a.ToString()));
    }
}

UndoRedoStack

public class UndoRedoStack
{
    private readonly Stack<IUndoableAction> undoStack = new Stack<IUndoableAction>();
    private readonly Stack<IUndoableAction> redoStack = new Stack<IUndoableAction>();

    /// <summary>
    /// ์ƒˆ๋กœ์šด ์•ก์…˜์„ ์ž…๋ ฅ๋ฐ›์•˜์„๋•Œ ๊ฐ IUndoableAction์„ 
    /// Implementํ•œ ํด๋ž˜์Šค์˜ ์•ก์…˜์„ ์ˆ˜ํ–‰ํ•˜๊ณ  ๊ธฐ์กด์˜ Redo ์Šคํƒ์€ ์ง€์›Œ์ง„๋‹ค.
    /// Undo ๋ฐ Redo ๋ฉ”์„œ๋“œ ์ˆ˜ํ–‰ ์‹œ Implement ๋œ ํด๋ž˜์Šค์˜ ๋‚ด์šฉ์„ ์ˆ˜ํ–‰ํ•œ๋‹ค.
    /// </summary>
    /// <param name="action"></param>
    public void Do(IUndoableAction action)
    {
        action.Do();
        undoStack.Push(action);

        redoStack.Clear();
    }

    public void Undo()
    {
        RunAction(undoStack, redoStack, f => f.Undo());
    }

    public void Redo()
    {
        RunAction(redoStack, undoStack, f => f.Do());
    }

    private static void RunAction(Stack<IUndoableAction> source, Stack<IUndoableAction> target, Action<IUndoableAction> undoRedo)
    {
        if (source.Count <= 0)
            return;

        var action = source.Pop();

        undoRedo(action);
        target.Push(action);
    }
}

Reference.

Last updated