2011-12-25 8 views
2

실행 취소/다시 실행을 지원해야하는 프로그램을 C#으로 작성했습니다. 이를 위해 Command 패턴을 정했다. tldr 일 때, 문서 상태를 조작하는 모든 조작은 문서의 이전 상태에 대해 알고있는 명령 오브젝트에 의해 수행되어야하며 변경이 필요하고 변경/실행 취소가 가능해야합니다.C#의 명령 패턴 및 복합 연산

간단한 조작에서는 문제가 없지만 한 번에 문서의 여러 부분에 영향을주는 작업이 있습니다. 마찬가지로 명령 객체는 실행 취소해야 할 경우를 위해 보존해야하는 모든 이전 상태를 알만큼 충분히 똑똑해야합니다.

공개 인터페이스를 사용하는 모든 상태가 노출되면 누군가가 인터페이스를 직접 호출하려고 시도 할 때 오용의 가능성이 있으므로 상태가 손상 될 수 있습니다. 내 insticts이 일을하는 가장 일반적인 방법은 특수 Command 클래스를 노출하는 것입니다 - 당신이 직접 문서의 상태를 조작 할 수 있도록, 당신이 할 수있는 모든 명령 개체에 액세스 할 수있는 명령 개체를 만들 것을 요청하는 것입니다 내부 상태이며 실행 취소/다시 실행을 적절히 지원할만큼 충분히 알 수 있습니다.

불행히도 C#은 친구 개념을 지원하지 않으므로 문서 내부에 액세스 할 수있는 Command 클래스를 만들 수 없습니다. 문서 클래스의 비공개 멤버를 다른 클래스에 노출시키는 방법이 있습니까, 아니면 많은 문서 내부를 노출시키지 않고도 필요한 것을 수행 할 수있는 다른 방법이 있습니까?

+0

명령 패턴이 아닌 실행 취소/다시 실행 작업을 처리 할 때는 일반적으로 Memento 패턴을 사용합니다. 명령 패턴은 "무언가를 실행"해야 할 때 더 적합합니다. 원격 제어를 프로그래밍 할 때 각 버튼에 명령이 주어집니다. – Patrick

+0

'불행히도 C#은'다행스럽게 '읽어야하는 친구의 개념을 지원하지 않습니다. 언어를 가지고 있으면 발을 쏘는 데 도움이되지 않습니다. –

답변

2

라이브러리를 배포하는 경우 문서가 내부 상태와 상호 작용하도록 '내부'메소드를 선언 할 수 있습니다. 이러한 메소드는 Command 클래스에서 사용되며 내부 메소드는 컴파일 된 어셈블리로 제한됩니다.

또는 Document에 내부 클래스를 중첩하여 Document의 내부 상태에 액세스하고 공용 인터페이스를 공개하도록 허용하면 Document는 해당 인터페이스에 의해 숨겨진 명령 클래스를 만듭니다.

+0

둘 다 완전히 확장 할 수없는 솔루션입니다. –

+0

@OndrejTucny 사용자 인터페이스에서 완전한 격리를 원한다면 Command 클래스를 사용자 코드에서 확장 할 수 없지만 'Command'를 다시 사용하여 실행 취소 가능한 다른 클래스로 Command 패턴을 확장하려는 경우 모든 클래스가 데이터 유형이 무엇이든간에 변경 사항을 실행 취소하는 데 사용할 수있는 인터페이스를 노출해야한다고 동의하지만 명령에서 실행 취소 조치를 제거합니다. – Caian

0

리플렉션 (Type.GetField(string, BindingFlags.Private) & 친구들)을 통해 비공개 또는 공개되지 않는 필드와 속성에 항상 액세스 할 수 있습니다.

클래스 (또는 필드/속성)의 맞춤 속성을 사용하여 각 명령에 대한 충분한 상태를 자동으로 잡아낼 수 있습니까?

+1

물건을 할 수 있습니다! =이 일을해야합니다. –

2

먼저 C#은 전체 어셈블리 내에서 공용 액세스를 허용하는 "친구"액세스 가능성을 선언하는 internal 키워드가 있습니다.

둘째, 조립 속성 InternalsVisibleTo로 "친구"접근성 can be extended to a second assembly, 당신은 당신의 명령에 대한 두 번째 프로젝트를 만들 수 있도록, 아직 문서의 내부는 내부 유지됩니다.

또는 명령 개체가 문서 클래스 내에 중첩되어 있으면 모든 개인 멤버에 액세스 할 수 있습니다.

마지막으로 복잡한 명령은 변경하기 전에 문서를 단순히 복제 할 수도 있습니다. 매우 최적화되지는 않았지만 쉬운 솔루션입니다.

0

문서의 다른 위치에서 명령을 변경하는 대신 다중 단계 작업의 시작과 끝을 표시하는 두 개의 더미 명령을 사용할 수 있습니다. BeginCommand와 EndCommand라고 부르 자. 먼저 BeginCommand를 실행 취소 스택에 놓고 다른 단계를 단일 명령으로 수행합니다. 각 명령은 문서의 한 위치에서만 변경됩니다. 그 이유는 스택을 언두 스택에도 밀어 넣기 때문입니다. 마지막으로 실행 취소 스택에서 EndCommand를 누릅니다.

실행 취소 할 때 실행 취소 스택에서 팝업 된 명령이 EndCommand인지 여부를 확인합니다. 이 경우 BeginCommand에 도달 할 때까지 실행을 계속합니다.

이렇게하면 다단계 명령이 다른 명령으로 작업을 위임하는 매크로 명령으로 바뀝니다. 이 매크로 명령 자체는 실행 취소 스택에 푸시되지 않습니다.

+1

또는 합성 명령을 사용할 수 있습니다 ... – decyclone