Command Pattern

 - 명령들을 캡슐화(클래스)

 -  명령을 수행 단위로 묶음

 -> 명령을 추상화


  특정 객체에 대한 특정 작업을 캡슐화 하여 요청을 하는 객체와 수행하는 객체를 분리한다.


 요청을 객체화 형태로 캡슐화 하면 요청에 대한 저장 및 로깅, 연산의 취소를 지원할 수 있다.


  1. interface Shape {
  2.         void draw(); // LSP(리스코프의 치환 법칙) : 자식은 부모로 대체 가능해야 한다.
  3. }
  4.  
  5. class Rect implements Shape {
  6.         @Override
  7.         public void draw() {
  8.                 System.out.println("Draw Rect");
  9.         }
  10. }
  11.  
  12. class Circle implements Shape {
  13.         @Override
  14.         public void draw() {
  15.                 System.out.println("Draw Circle");
  16.         }
  17. }
  18.  
  19. interface ICommand {
  20.         void execute();
  21.  
  22.         boolean canUndo();
  23.  
  24.         void undo();
  25. }
  26.  
  27. abstract class AddCommand implements ICommand {
  28.         private final List<Shape> shapes;
  29.  
  30.         public AddCommand(List<Shape> s) {
  31.                 this.shapes = s;
  32.         }
  33.  
  34.         @Override
  35.         public void execute() {
  36.                 shapes.add(createShape());
  37.         }
  38.  
  39.         @Override
  40.         public boolean canUndo() {
  41.                 return true;
  42.         }
  43.  
  44.         @Override
  45.         public void undo() {
  46.                 shapes.remove(shapes.size() - 1);
  47.         }
  48.  
  49.         public abstract Shape createShape();
  50. }
  51.  
  52. class AddRectCommand extends AddCommand {
  53.         public AddRectCommand(List<Shape> s) {
  54.                 super(s);
  55.         }
  56.  
  57.         @Override
  58.         public Shape createShape() {
  59.                 return new Rect();
  60.         }
  61. }
  62.  
  63. class AddCircleCommand extends AddCommand {
  64.         public AddCircleCommand(List<Shape> s) {
  65.                 super(s);
  66.         }
  67.  
  68.         @Override
  69.         public Shape createShape() {
  70.                 return new Circle();
  71.         }
  72. }
  73.  
  74. class DrawCommand implements ICommand {
  75.         private final List<Shape> shapes;
  76.  
  77.         public DrawCommand(List<Shape> s) {
  78.                 shapes = s;
  79.         }
  80.  
  81.         @Override
  82.         public void execute() {
  83.                 for (Shape e : shapes) {
  84.                         e.draw();
  85.                 }
  86.         }
  87.  
  88.         @Override
  89.         public boolean canUndo() {
  90.                 return true;
  91.         }
  92.  
  93.         @Override
  94.         public void undo() {
  95.                 System.out.println("Screen Cleared!!!");
  96.         }
  97. }
  98.  
  99. class MacroCommand implements ICommand {
  100.         // Composite Pattern
  101.         private List<ICommand> commands = new ArrayList<>();
  102.  
  103.         public void addCommand(ICommand c) {
  104.                 commands.add(c);
  105.         }
  106.  
  107.         // Ctrl + C  / Ctrl + D
  108.         // Ctrl + D
  109.        
  110.         @Override
  111.         public void execute() {
  112.                 for (ICommand e : commands) {
  113.                         e.execute();
  114.                 }
  115.         }
  116.  
  117.         @Override
  118.         public boolean canUndo() {
  119.                 for (int i = 0; i < commands.size(); i++) {
  120.                         if (commands.get(i).canUndo() == false)
  121.                                 return false;
  122.                 }
  123.  
  124.                 return true;
  125.         }
  126.  
  127.         @Override
  128.         public void undo() {
  129.                 int n = commands.size() - 1;
  130.                 while (>= 0) {
  131.                         commands.get(n).undo();
  132.                         n--;
  133.                 }
  134.         }
  135.  
  136. }
  137.  
  138. public class Ex1 {
  139.         private static Scanner scanner;
  140.  
  141.         public static void main(String[] args) {
  142.                 scanner = new Scanner(System.in);
  143.                 List<Shape> shapes = new ArrayList<>();
  144.  
  145.                 Stack<ICommand> commandStack = new Stack<>();
  146.                 Stack<ICommand> redoStack = new Stack<>();
  147.                
  148.                 MacroCommand mc = new MacroCommand();
  149.                 mc.addCommand(new AddRectCommand(shapes));
  150.                 mc.addCommand(new AddCircleCommand(shapes));
  151.                 mc.addCommand(new DrawCommand(shapes));
  152.                 mc.execute();
  153.                
  154.                 commandStack.add(mc);
  155.  
  156.                 ICommand command = null;
  157.                 while (true) {
  158.                         System.out.print("choice : ");
  159.                         int cmd = scanner.nextInt();
  160.  
  161.                         switch (cmd) {
  162.                         case 1:
  163.                                 command = new AddRectCommand(shapes);
  164.                                 command.execute();
  165.                                 commandStack.push(command);
  166.                                 break;
  167.  
  168.                         case 2:
  169.                                 command = new AddCircleCommand(shapes);
  170.                                 command.execute();
  171.                                 commandStack.push(command);
  172.                                 break;
  173.  
  174.                         case 9:
  175.                                 command = new DrawCommand(shapes);
  176.                                 command.execute();
  177.                                 commandStack.push(command);
  178.                                 break;
  179.  
  180.                         case -1:
  181.                                 command = redoStack.pop();
  182.                                 command.execute();
  183.  
  184.                         case 0:
  185.                                 // Undo(ctrl + z)
  186.                                 command = commandStack.pop();
  187.  
  188.                                 if (command.canUndo()) {
  189.                                         command.undo();
  190.                                         redoStack.add(command);
  191.                                 }
  192.                                 break;
  193.                         }
  194.  
  195.                 }
  196.         }
  197. }


'java > design_pattern' 카테고리의 다른 글

Bridge Pattern - 브릿지 패턴  (0) 2014.07.01
Memento Pattern - 메멘토 패턴  (0) 2014.07.01
Proxy Pattern - 대리자 패턴  (0) 2014.07.01
Iterator Pattern - 열거자  (0) 2014.07.01
Visitor Pattern - 방문자 패턴  (0) 2014.07.01

+ Recent posts