명령 패턴:매개변수를 명령에 전달하는 방법은 무엇입니까?

StackOverflow https://stackoverflow.com/questions/104918

  •  01-07-2019
  •  | 
  •  

문제

내 질문은 다음과 같은 추상화(C# 코드)가 있는 명령 패턴과 관련이 있습니다.

public interface ICommand
{
    void Execute();
}

애플리케이션에서 엔터티를 삭제하는 것을 목표로 하는 간단하고 구체적인 명령을 살펴보겠습니다.ㅏ Person 예를 들어.

나는 DeletePersonCommand, 구현하는 ICommand.이 명령에는 Person 매개변수로 삭제하려면 다음 경우에 삭제하세요. Execute 메소드가 호출됩니다.

매개변수화된 명령을 관리하는 가장 좋은 방법은 무엇입니까?명령을 실행하기 전에 명령에 매개변수를 전달하는 방법은 무엇입니까?

도움이 되었습니까?

해결책

생성자나 setter 주입(또는 이에 상응하는 방법)을 통해 매개변수를 명령 개체와 연결해야 합니다.아마도 다음과 같을 것입니다:

public class DeletePersonCommand: ICommand
{
     private Person personToDelete;
     public DeletePersonCommand(Person personToDelete)
     {
         this.personToDelete = personToDelete;
     }

     public void Execute()
     {
        doSomethingWith(personToDelete);
     }
}

다른 팁

생성자나 설정자를 통해 데이터를 전달하는 것은 작동하지만 명령 작성자가 명령에 필요한 데이터를 알아야 합니다.

"컨텍스트" 아이디어는 정말 좋은데, 저는 얼마 전에 그것을 활용한 (내부) 프레임워크를 작업하고 있었습니다.

사용 가능한 데이터에 대한 명명된 액세스를 제공하기 위해 컨트롤러(사용자와 상호 작용하는 UI 구성 요소, 사용자 명령을 해석하는 CLI, 수신 매개 변수 및 세션 데이터를 해석하는 서블릿 등)를 설정하면 명령이 원하는 데이터를 직접 요청할 수 있습니다.

나는 이와 같은 설정이 허용하는 분리를 정말 좋아합니다.레이어링에 대해 다음과 같이 생각해보세요.

User Interface (GUI controls, CLI, etc)
    |
[syncs with/gets data]
    V
Controller / Presentation Model
    |                    ^
[executes]               |
    V                    |
Commands --------> [gets data by name]
    |
[updates]
    V
Domain Model

이 작업을 "올바르게" 수행하면 모든 유형의 사용자 인터페이스에서 동일한 명령 및 프레젠테이션 모델을 사용할 수 있습니다.

한 단계 더 나아가서 위의 "컨트롤러"는 매우 일반적입니다.UI 컨트롤은 다음 사항만 알아야 합니다. 이름 호출할 명령에 대해 설명합니다. 즉, 사용자(또는 컨트롤러)는 해당 명령을 생성하는 방법이나 명령에 필요한 데이터에 대해 알 필요가 없습니다.이것이 바로 이곳의 진짜 장점입니다.

예를 들어 맵에서 실행할 명령의 이름을 보유할 수 있습니다.구성 요소가 "트리거"될 때마다(일반적으로 actionPerformed) 컨트롤러는 명령 이름을 찾아 인스턴스화하고 실행을 호출한 다음 실행 취소 스택(사용하는 경우)에 푸시합니다.

몇 가지 옵션이 있습니다:

속성이나 생성자로 매개변수를 전달할 수 있습니다.

다른 옵션은 다음과 같습니다.

interface ICommand<T>
{
    void Execute(T args);
}

그리고 모든 명령 매개변수를 값 개체에 캡슐화합니다.

명령 개체를 만들 때 사람을 전달합니다.

ICommand command = new DeletePersonCommand(person);

따라서 명령을 실행할 때 알아야 할 모든 것을 이미 알고 있습니다.

class DeletePersonCommand : ICommand
{
   private Person person;
   public DeletePersonCommand(Person person)
   {
      this.person = person;
   }

   public void Execute()
   {
      RealDelete(person);
   }
}

내 구현은 다음과 같습니다(Juanma가 제안한 ICommand 사용).

public class DeletePersonCommand: ICommand<Person>
{
    public DeletePersonCommand(IPersonService personService)
    {  
        this.personService = personService;
    }

    public void Execute(Person person)
    {
        this.personService.DeletePerson(person);
    }
}

IPersonService는 IPersonRepository일 수 있으며 명령이 어떤 "계층"인지에 따라 다릅니다.

이 경우 Command 개체를 사용하여 수행한 작업은 기본적으로 맵인 Context 개체를 만드는 것입니다.맵에는 키가 상수이고 값이 명령 구현에서 사용되는 매개변수인 이름 값 쌍이 포함되어 있습니다.이후 명령이 이전 명령의 컨텍스트 변경에 따라 달라지는 명령 체인이 있는 경우 특히 유용합니다.

그래서 실제 방법은

void execute(Context ctx);

생성자에서 필드로 저장됩니다.

또한 실행 취소 스택이나 파일 지속성을 위해 최종적으로 ICommand를 직렬화할 수 있도록 만들고 싶을 것입니다.

C#/WPF의 패턴을 기반으로 ICommand 인터페이스(System.Windows.Input.ICommand)는 개체를 Execute 및 CanExecute 메서드의 매개 변수로 사용하도록 정의됩니다.

interface ICommand
            {
                bool CanExecute(object parameter);
                void Execute(object parameter);
            }

이를 통해 명령을 ICommand를 구현하는 사용자 정의 명령 개체의 인스턴스인 정적 공개 필드로 정의할 수 있습니다.

public static ICommand DeleteCommand = new DeleteCommandInstance();

이러한 방식으로 관련 개체(귀하의 경우에는 사람)가 실행이 호출될 때 전달됩니다.그런 다음 Execute 메서드는 개체를 캐스팅하고 Delete() 메서드를 호출할 수 있습니다.

public void Execute(object parameter)
            {
                person target = (person)parameter;
                target.Delete();
            } 

사용하려는 매개변수를 포함하는 CommandArgs 개체를 만들어야 합니다.Command 개체의 생성자를 사용하여 CommandArgs 개체를 삽입합니다.

DeletePersonCommand는 생성자나 메소드에 매개변수를 가질 수 있습니다.DeletePersonCommand에는 Execute()가 있으며 실행에서는 Execute() 호출 이전에 Getter/Setter가 전달한 속성을 확인할 수 있습니다.

생성자에 필요한 인수를 추가하겠습니다. DeletePersonCommand.그럼 언제 Execute() 호출되면 생성 시 객체에 전달된 매개변수가 사용됩니다.

"Person"이 일종의 IDeletable 인터페이스를 구현하도록 한 다음 엔터티가 사용하는 기본 클래스나 인터페이스를 명령이 사용하도록 합니다.이렇게 하면 엔터티를 IDeletable로 캐스팅하려고 시도하는 DeleteCommand를 만들 수 있으며, 작동하는 경우 .Delete를 호출합니다.

public class DeleteCommand : ICommand
{
   public void Execute(Entity entity)
   {
      IDeletable del = entity as IDeletable;
      if (del != null) del.Delete();
   }
}
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top