웹 개발 중인 디자인 모델 #2 Memento

업데이트된 버전 보기


소개하다.


당신들 중 일부가 기억할 수 있는 바와 같이, 내가 전에 말한 글에서, 나는 세 가지 예로 이 명령을 설명할 것이다. 그것이 바로 UI 도구 패키지, CQRS 응용 프로그램, Electron의 취소/재실행이다.비록 나는 후자를 제공하지 않았지만, 이유는 매우 간단하다. 나는 나쁜 놈이다.
그 밖에 이 예로 다른 행위 모델1을 설명하는 것은 나에게 더 의미가 있다. 이것은 Gang of Four 중의 고전적인 모델인 메모토에 속한다.

기념품


Bla, bla, bla. Code please

예: 계산기


계산기를 사용하고 있다고 가정해 보세요.너는 표현식을 제공해라. 그것은 너를 위해 수학 연산을 할 것이다.간단하게 보기 위해서 우리는 그 중의 한 가지 방법만 고려한다. power이 계산기 뒤의 논리는 Calculator라는 클래스에서 다음과 같이 보일 것이다.
class Calculator {
    // State
    private string display;
    // and a whole lot of unrelated other fields

    // Resolves expressions like x^y
    private power(string expression): number;

    // Writes on display
    setState(string display): void;

    // Parse what's on the display, calculates and overrides the display
    calculate(): number;
}
맑은 날에, 우리는 이 프로그램을 위해 취소 메커니즘을 실현하기로 결정했다.이 메커니즘을 실현하는 첫 번째 생각은 방금 한 일의 반함수를 간단하게 응용하는 것일 수도 있다.

불행히도, 이것은 power 함수에 작용하지 않는다.
예를 들어 취소y = power(x, 2)sqrt(y, 2)를 적용하지만 power(2, 2)power(-2, 2)는 같은 결과를 낳기 때문에 사용x만으로는 명확하게 얻을 수 없다y.
이 때 calculateundo 이 스냅샷을 사용하여 계산기 상태를 재설정할 때, 스냅샷에 이전 상태를 저장하는 것이 더욱 간단하고 효과적입니다.
Memento는 이 문제를 해결하기 위해 간결한 방법을 제공했다.

이게 어떻게 된 일입니까?


Intent
Without violating encapsulation, capture and externalize an object's internal
state so that the object can be restored to this state later.


네, 방금 이 수수께끼 퀴즈를 이겼습니다. 4인방에서 왔습니다.
이러한 생각은 매우 간단하다. 우리는 나중에 회복할 수 있도록 대상의 내부 상태에 대한 스냅샷을 체계적으로 저장하는 방법을 원한다.

만약 당신이 왜 상태를 노출해서는 안 되는지 알고 싶다면, 아마도 당신은 여전히 결합을 두려워해서는 안 될 것이다.이거 큰일날 거야.그러나, 당신은 여전히 제때에 그것을 복구할 수 있습니다.여기서 기다릴게.
...
완성우리는 실천 중인 메모토부터 시작할 수 있다.

실천 중의 모델



첫 번째: 왜 이런 도안을 기념품이라고 합니까?메멘토는 알람2으로 안전하게 번역할 수 있는 라틴어다.스토리지 관심 분야Calculator 상태 섹션의 대상입니다.Calculator, 즉 국가의 기원인 곳으로 시작용자로 불리며 이 이야기의 세 번째 역할은 전체 일을 책임지는 사람으로 간수인으로 불린다.
마지막으로 Memento의 참여자와 해당 역할은 다음과 같습니다.

  • 발기인:
  • 내부 상태를 저장할 기념품을 만들기;
  • 기념품으로 상태 회복;

  • 기념품:
  • 발기자 내부 상태의 변하지 않는 스냅샷을 저장한다.
  • 발기인만 방문할 수 있다.

  • 관리자:
  • 상점 기념품;
  • 기념품을 조작하거나 읽지 않는다.
  • 실천 과정에서 이러한 것들은 다음과 같다.
    // Originator
    class Calculator {
        private string display;
    
        private power(string expression): number;
    
        setState(string display): void;
        calculate(): number;
        save(): Snapshot;
        restore(Snapshot snapshot): void; 
    }
    
    // Memento
    class Snapshot {
        private string state;
    
        getState(): state;
    }
    
    // CareTaker
    class Application {
        Calculator calculator;
        Array<Snapshot> undoSnapshots;
        Array<Snapshot> redoSnapshots;
    
        calculate(): void {
            const snapshot = this.calculator.save()
            this.undoSnapshots.push(snapshot)
            this.redoSnapshots = []
            this.calculator.calculate()
        }
    
        undo(): void {
            const snapshot = this.undoSnapshots.pop()
            this.redoSnapshots.push(snapshot)
            this.calculator.restore(snapshot)
        }
    
        redo(): void {
            const snapshot = this.redoSnapshots.pop()
            this.undoSnapshots.push(snapshot)
            this.calculator.restore(snapshot)
        }
    }
    

    좋아요!나 내일 이s**t 어떻게 써?


    Memento가 있어서 우리는 행운이라고 할 수 있다. 당신은 아주 복잡한 용례를 찾지 않아도 그것을 실현할 수 있다.지금까지 장면을 취소하거나 다시 만드는 것이 가장 흔한 부분이지만, 대상을 이전 단계로 복원해야 할 때마다 쉽게 다시 사용할 수 있다.
    너는 다른 예가 필요하지 않니?
    웹 프로그램의 프로필 나이가 있다고 가정하십시오.프로파일 편집을 클릭하면 특정 작업이 완료되면 취소됩니다.매번 이런 상황이 발생할 때마다 AJAX 호출을 통해 사용자 정보를 다시 얻으려고 하지 않으면 취소할 때 복구할 수 있도록 기념품을 저장하는 것이 가장 좋다.
    Memento가 이 목표를 실현하는 유일한 방법입니까?아니요. 이런 상황에서 또 다른 흔한 모델은 원형입니다. 다음 회 주제일 수도 있습니다.아니면, 누가 알겠는가?어쨌든 Prototype에 관해서는 대상 상태 복사본을 만드는 다른 방법을 제공하지만 방식이 다르다는 것을 알아야 합니다.
    한 마디로 하면 물체의 역사를 통과해야 할 때 스냅숏을 찍으면 생활이 더욱 수월해진다.

    너의 다음 문제는 아마도 이것이 편리한가 아니면 필요한가?우리는 계산기 예시에서 때때로 마지막 동작을 반전시켜 이전 상태에 도달하지 못할 때가 있다.불행하게도, 이것은 거스를 수 없는 수학 함수에 적용될 뿐만 아니라, 네 방법이 부작용이 있을 때마다 적용된다.이러한 상황에서 일반적으로 스냅샷을 찍는 것은 안전하게 이전 상태로 회복하는 유일한 방법이다.

    그렇다면 함정은 어디에 있을까?


    이런 모델에는 네가 반드시 매우 주의해야 할 몇 가지 문제가 있다.
    첫 번째도 가장 뚜렷한 것은 복구 대상이 크면 스냅숏 역사를 가지고 있는 것이 번거로워질 수 있다는 것이다.이 문제를 해결하는 방법 중 하나는 다른 변경 사항만 저장하는 것이지만, 이것은 적용할 스냅샷의 순서를 정확히 알고 있는 장면에만 적용됩니다. 예를 들어 실행 취소/다시 실행 중.
    또 다른 은밀한 이유는 스냅샷이 올바르게 만들어지지 않으면 역사를 두루 돌아다닐 때 오류를 만들고 축적하기 쉽다는 것이다.예를 하나 들자.
    유사 이래 가장 어리석은 게임을 가정해 보자. 버튼을 눌렀을 때마다 10점을 얻고, 점수가 100이 되면 휘장을 받는다.우리는 이곳에서 취소 메커니즘을 실현하려고 하기 때문에 score 변수를 클릭할 때마다 스냅샷을 저장한다.
    우리는 최대 100번을 클릭해서 휘장을 하나 얻었습니다. 우리는 취소했습니다. 우리는 다시 클릭해서 두 번째 휘장을 얻었습니다.

    왜 이러지?스냅샷에서 배지를 추적하는 것을 잊었기 때문에 취소할 때, 우리는 점수만 회복했을 뿐, 배지 목록을 정리하지 않았다.

    대화를 적게 하고 행동을 많이 하다


    You can find a more detailed version of these examples here

    shikaan/디자인 모드

    실제 코드에서 디자인 모델을 사용하는 예시

    디자인 모델

    Examples of usage of design patterns in real life code

    These are the reference resources for


    드디어 인코딩 시작!
    소개에서 약속한 대로 명령과 메모토를 통해 같은 철회 문제를 해결하는 방법을 보여 드리겠습니다.

    Disclaimer
    I decided to not use Electron for this example for the simple reason that it makes the whole thing more complicated for people not familiar with it and it's not bringing any value to Electron experts. If you're really upset about this, drop a comment and I will add also that example.


    이 예는 매우 간단한 React 프로그램으로 타일을 정렬해서 이기는 게임이어야 한다.
    그것은 기본적으로 keyDown 에 탐지기를 설치하고, 이를 바탕으로 방법 (Memento) 을 호출하거나 명령 (command) 을 보낸다.
    Memento 예시에서, 우리는 Game 구성 요소가 하나 있는데, 이것은 모든 게임 논리를 처리한다. 그것은 타일을 이동하고, 타일을 선택하고, 사용자가 승리했는지 계산하는 것이다.이것은 그것을 완벽한 발기자로 만들었다. 왜냐하면 그것도 우리의 저장 상태이기 때문에, 우리는 취소를 통해 복구하기를 희망할 수도 있다.발기인으로서 창설과 복구Snapshots를 책임진다는 것을 의미한다.Snapshot는 당연히 기념품이다. Game ES6 모듈에 있어서는'사적인'것이기 때문에 KeyboardEventHandler(또는 관리자)가 그것을 알지 못하게 한다.
    명령 예시에서, 우리는 호출 프로그램을 충당하는 추가 구성 요소가 있습니다. CommandManagerGameKeyboardEventHandler의 역할은 변화가 없지만 실현에 따라 작업 방식이 다르다.Game는 현재 명령의 수신자이고 KeyboardEventHandler는 고객이며 Command의 유일한 소유자이다.
    보시다시피 Command와 Memento를 교환해서 사용할 수 있습니다. 봉인된 동작 ((moveSelectedTile) 은 순수한 동작이고 부작용이 없기 때문에 우리는 실제적으로 스냅샷을 사용해서 상태를 재구성할 필요가 없습니다. 역방향 함수를 사용하면 충분합니다.
    이것은 기념품과 명령이 공존할 수 없다는 것을 의미하는 것입니까?절대 아니야.사실상, 명령에서 봉인 takeSnaphot 방법으로 CareTakerOriginator 을 결합할 수 있습니다.또는, 당신은 봉인moveSelectedTile할 수 있습니다. 우리가 이미 한 것처럼 명령에서 이 방법을 실행하는 것 외에 스냅샷도 찍을 수 있습니다.마지막으로 Command와 Mememto를 함께 살게 하는 가장 흔한 방식이다.
    the repo부터 시작해서 연습으로 실험할 수 있다.만약 네가 사악하다면 다른 사람의 파티를 파괴하고 싶다면, 너는 공관을 제출할 수 있다.

    마지막 말


    좋아, 우리가 책상 위에 지식과 카드를 섞기 시작하면서 일은 더욱 흥분되기 시작했다.이것은 틀림없이 시간의 추이에 따라 개선될 것이다. 그러므로 견지해야 한다. D
    만약 당신이 어떤 피드백을 가지고 있다면 ("인코딩하는 방법을 알려주지 마세요. 당신은 나의 진정한 엄마가 아닙니다.")의견("너의 코드는 개똥 같지만 너의 모인은 너무 좋다"), 평론("네, 그래요. 행동 패턴이 멋있어요. 다음은 뭐예요?"),이 시리즈를 더 잘 할 수 있도록 댓글이나 댓글을 남겨주세요.
    다음까지!
    1 . 만약 당신이 행동 패턴이 무엇인지 확실하지 않다면, 한번 보세요
    2 . 이 점을 잊지 않기 위해서는 기억과 기억이 같은 기원을 가지고 있다는 것을 기억해야 한다.기억과 관련된 것을 기억하는 기억 기교.번영!

    좋은 웹페이지 즐겨찾기