[디자인 패턴] 커맨드 패턴 (Command Pattern)

최진민·2021년 11월 15일
0

디자인 패턴

목록 보기
6/10
post-thumbnail
  • 정의
  • 사용 이유
  • 구현

🇳🇴 1. 커맨드 패턴 ?

  • 커맨트 패턴 (Command Pattern)
    • 객체의 행위(method)를 클래스로 생성하여 캡슐화하는 디자인 패턴
    • A 객체에서 B 객체의 메서드를 실행하기 위해서는 B를 참조하고 있어야 한다. (의존성 발생) => 커맨드 패턴을 통해 의존성 제거
    • 어떠한 이벤트에 대해 실행될 기능이 다양하면서도 변경이 필요한 경우에 이벤트를 발생시키는 클래스를 변경하지 않고 재사용하고자 할때 유용한 패턴


🏁 2. 사용 이유

  • 문서 편집기에 대한 예제를 살펴보자

    public class NonTextEditor {
        private Copier copier;
    
        public NonTextEditor(Copier copier) {
            this.copier = copier;
        }
    
        public void copy() {
            copier.copy();
        }
    }
    public class Copier {
        public void copy(){
            System.out.println("복사");
        }
    }
    public class User {
        public static void main(String[] args) {
            Copier copier = new Copier();
    
            NonTextEditor nonTextEditor = new NonTextEditor(copier);
    
            nonTextEditor.copy();
        }
    }
    
    print >>>
    복사
    • 현재 문서 편집기의 기능은 복사만 존재하지만 붙혀넣기자르기와 같이 새로운 기능을 추가할 때, 코드 변경은 불가피하다.

      public class NonTextEditor {
          private Copier copier;
          private Paster paster;
          private Cutter cutter;
          private Skill skill;
      
          public NonTextEditor(Copier copier, Paster paster, Cutter cutter) {
              this.copier = copier;
              this.paster = paster;
              this.cutter = cutter;
          }
      
          public void setSkill(Skill skill) {
              this.skill = skill;
          }
      
          public void useEditor() {
              switch (this.skill) {
                  case COPIER:
                      copier.copy();
                      break;
                  case PASTER:
                      paster.paste();
                      break;
                  case CUTTER:
                      cutter.cut();
                      break;
              }
          }
      }
      public class Copier {
          public void copy(){
              System.out.println("복사");
          }
      }
      
      public class Paster {
          public void paste() {
              System.out.println("붙혀넣기");
          }
      }
      
      public class Cutter {
          public void cut() {
              System.out.println("잘라내기");
          }
      }
      
      //enum
      public enum Skill {
          COPIER, PASTER, CUTTER
      }
      public class User {
          public static void main(String[] args) {
              Copier copier = new Copier();
              Paster paster = new Paster();
              Cutter cutter = new Cutter();
      
              NonTextEditor nonTextEditor = new NonTextEditor(copier, paster, cutter);
      
              nonTextEditor.setSkill(Skill.COPIER);
              nonTextEditor.useEditor();
      
              nonTextEditor.setSkill(Skill.PASTER);
              nonTextEditor.useEditor();
      
              nonTextEditor.setSkill(Skill.CUTTER);
              nonTextEditor.useEditor();
          }
      }
    • 기능이 많아질수록, 객체에 대한 의존성많아진다.

    • useEditor()분기가 증가한다.

    • OCP (Open-Closed Principle) 위반



🇰🇷 3. 구현

  • 각 기능을 클래스로 생성하여 인터페이스로 캡슐화한다.

  • 기능을 사용하는 클래스(TextEditor)에서 인터페이스의 메서드를 호출한다.

    public interface EditorCommand {
        void useEditor();
    }
    public class CopyCommand implements EditorCommand {
        private Copier copier;
    
        public CopyCommand(Copier copier) {
            this.copier = copier;
        }
    
        @Override
        public void useEditor() {
            copier.copy();
        }
    }
    ////
    public class PasteCommand implements EditorCommand {
        private Paster paster;
    
        public PasteCommand(Paster paster) {
            this.paster = paster;
        }
    
        @Override
        public void useEditor() {
            paster.paste();
        }
    }
    ////
    public class CutCommand implements EditorCommand {
        private Cutter cutter;
    
        public CutCommand(Cutter cutter) {
            this.cutter = cutter;
        }
    
        @Override
        public void useEditor() {
            cutter.cut();
        }
    }
    public class TextEditor {
        private EditorCommand editorCommand;
    
        public void setEditorCommand(EditorCommand editorCommand) {
            this.editorCommand = editorCommand;
        }
    
        public void useEditor() {
            editorCommand.useEditor();
        }
    }
    • 문서편집기EditorCommand에 대한 의존성만 존재.
    • 기능을 추가할 때는 XXXXXXCommand를 추가하면 되기 때문에 OCP에 위배되지 않는다.
    • 단점 : Git을 통해 프로젝트 구조를 보면 알 수 있지만 nonadapt을 비교했을 때, 클래스의 수가 많아진 것을 볼 수 있다.
  • Git : https://github.com/JinMinChoi/Design-Pattern/tree/master/src/command

profile
열심히 해보자9999

0개의 댓글