{"id":332,"date":"2020-05-28T17:34:52","date_gmt":"2020-05-28T08:34:52","guid":{"rendered":"http:\/\/batmask.dothome.co.kr\/?p=332"},"modified":"2025-09-11T18:59:36","modified_gmt":"2025-09-11T09:59:36","slug":"design-pattern-command-pattern","status":"publish","type":"post","link":"http:\/\/batmask.net\/index.php\/2020\/05\/28\/332\/","title":{"rendered":"Design Pattern: Command Pattern"},"content":{"rendered":"\n<p> \uac1d\uccb4\uc5d0\uc11c \ub2e4\ub978 \uac1d\uccb4\ub85c request\ub97c \ubcf4\ub0bc \ub54c,  request \ub0b4\uc6a9\uc774 \ubcf5\uc7a1\ud574 \uc9c0\uac70\ub098 \ud655\uc7a5\uc774 \ud544\uc694\ud558\uba74, \ud504\ub85c\ud1a0\ucf5c\uc744 \ub530\ub85c \uc124\uacc4\ud558\uac8c\ub41c\ub2e4. \uadf8\ub807\uac8c \ud574\uc57c \ubcf4\ub2e4 \uc720\uc5f0\ud574\uc9c0\uae30 \ub54c\ubb38\uc774\ub2e4.   request\uc5d0 \ub300\ud55c \ud504\ub85c\ud1a0\ucf5c\uc744 \ubcc4\ub3c4\uc758 Command \uc624\ube0c\uc81d\ud2b8\ub85c \uad6c\ud604\ud558\ub294 \ubc29\ubc95\uc774 \ubc14\ub85c  Command Pattern\uc774\ub2e4. request\ub97c \ubcf4\ub0b4\ub294 Invoker \uac1d\uccb4\ub294 \uc774\ub97c \ubc1b\ub294 Reciever \uac1d\uccb4\uc5d0 \ub300\ud55c \uc815\ubcf4\uac00 \uc5c6\uc5b4\ub3c4 \ub418\uae30 \ub54c\ubb38\uc5d0(Command \uac1d\uccb4\uac00 \uac16\uace0\uc788\ub2e4), \ub450 \uac1d\uccb4\uac04 coupling\uc744 \uc81c\uac70\ud560 \uc218 \uc788\ub2e4. <\/p>\n\n\n\n<p>Command Pattern\uc758 \uc2e4\uc81c \uc608\ub85c\ub294 Qt\uc5d0\uc11c QAction\uc744 \ub4e4 \uc218 \uc788\ub2e4. \uc774 \ud074\ub798\uc2a4\uac00 Command \ud074\ub798\uc2a4\uc5d0 \ud574\ub2f9\ud55c\ub2e4. \uba85\ub839\uc5b4\ub97c QAction \uac1d\uccb4\ub85c \uc0dd\uc131\ud558\uace0, \uba54\ub274\ub098 \ud234\ubc14\uc5d0 \uc774\ub97c \ud560\ub2f9\ud574\uc8fc\uba74 \uba54\ub274\uac00 \uc2e4\ud589\ub418\uac70\ub098 \ud234\ubc14 \ubc84\ud2bc\uc774 \ub20c\ub9b4 \ub54c, \uc774 QAction \uac1d\uccb4\uac00 \uc218\ud589\ub41c\ub2e4. QAction \uac1d\uccb4\ub294 \uc0dd\uc131\ud560 \ub54c, Receiver \uac1d\uccb4\uc5d0 \ub300\ud55c \uc815\ubcf4\uac00 \uc8fc\uc5b4\uc9c0\ubbc0\ub85c \uba54\ub274\ub098 \ud234\ubc14\uc5d0\uc11c Reciever\ub97c \ubab0\ub77c\ub3c4, \uc790\uc5f0\uc2a4\ub7fd\uac8c Reciever\ub85c \uc804\ub2ec\ub418\uac8c \ub41c\ub2e4.<\/p>\n\n\n\n<p>Command Pattern\uc744 \uc0ac\uc6a9\ud558\uba74 \uc5ec\ub7ec \uc7a5\uc810\uc774 \uc788\ub2e4. Command \uc790\uccb4\uac00 \ub3c5\ub9bd\uc801\uc774\ubbc0\ub85c, \uc2a4\ucf00\uc974\ub7ec\uc758 \uc54c\ub78c\ucc98\ub7fc command\uc758 \uc218\ud589\uc744 \ubc14\ub85c\ud558\uc9c0 \uc54a\uace0 \ud2b9\uc815\uc2dc\uc810\uc73c\ub85c \uc720\ubcf4\ub3c4 \uac00\ub2a5\ud558\ub2e4. \ub610, undo \uae30\ub2a5\uc744 \uc774 \ud328\ud134\uc73c\ub85c \uad6c\ud604\ud558\uba74, \ucee4\ub9e8\ub4dc \ubcc4\ub85c undo\ub97c \uc9c4\ud589\ud558\uc5ec multi-level undo\uc758 \uad6c\ud604\uc774 \uc6a9\uc774\ud574\uc9c4\ub2e4. undo\uc758 \uad6c\ud604\uc774 \uc27d\uc9c0\ub9ce\uc740 \uc54a\uae30 \ub54c\ubb38\uc5d0, \uc2e4\uc81c undo\uc758 \uad6c\ud604\uc740 Memento pattern\uc758 \uc0ac\uc6a9\uc744 \uace0\ub824\ud574\uc57c \ud55c\ub2e4.<br> \ub9ce\uc774 \uc0ac\uc6a9\ub418\ub294 \ud328\ud134\uc73c\ub85c, \uadf8 \ub9ce\uc740 \uc6a9\ub3c4\ub4e4\uc740 <a href=\"https:\/\/en.wikipedia.org\/wiki\/Command_pattern\">\uc704\ud0a4 \ud398\uc774\uc9c0<\/a> Uses \ud56d\ubaa9\uc5d0\uc11c \ud655\uc778 \uac00\ub2a5\ud558\ub2e4. \ub610\ud55c, \uc880 \ub354 \uc790\uc138\ud55c \uc124\uba85\uc740 <a href=\"https:\/\/refactoring.guru\/design-patterns\/command\">refactoring.guru<\/a> \uc5d0\uc11c\ub3c4 \ucc3e\uc544\ubcfc \uc218 \uc788\ub2e4.<\/p>\n\n\n\n<p>UML \ub2e4\uc774\uc5b4\uadf8\ub7a8\uc740 \ub2e4\uc74c\uacfc \uac19\ub2e4. ( <a href=\"https:\/\/en.wikipedia.org\/wiki\/Command_pattern\">\uc704\ud0a4 \ud398\uc774\uc9c0 \ucc38\uc870<\/a> ) <\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"660\" height=\"240\" src=\"http:\/\/batmask.dothome.co.kr\/wordpress\/wp-content\/uploads\/2020\/05\/W3sDesign_Command_Design_Pattern_UML.jpg\" alt=\"\" class=\"wp-image-572\" srcset=\"http:\/\/batmask.net\/wordpress\/wp-content\/uploads\/2020\/05\/W3sDesign_Command_Design_Pattern_UML.jpg 660w, http:\/\/batmask.net\/wordpress\/wp-content\/uploads\/2020\/05\/W3sDesign_Command_Design_Pattern_UML-300x109.jpg 300w\" sizes=\"auto, (max-width: 660px) 100vw, 660px\" \/><\/figure>\n\n\n\n<p>Invoker\ub294 Reciever\uc5d0 \ub300\ud55c \uc815\ubcf4\ub97c \uac16\uc9c0 \uc54a\ub294\ub2e4. Receiver\ub294 Concrete Command \uac1d\uccb4\uac00 \uac00\uc9c0\uace0 \uc788\ub2e4. Command Interface\ub294 Invoker\uac00 \ud638\ucd9c\ud560 execute() \ub2e8\uc77c \uc778\ud130\ud398\uc774\uc2a4\ub97c \uac16\ub294\ub2e4. Invoker\uc5d0 Concrete command\ub97c \ud560\ub2f9\ud574\uc8fc\ub294\uac74 Client \uac1d\uccb4\uac00 \ud574\uc8fc\ub294 \uc77c\uc774\ub2e4. Command \uac1d\uccb4\ub294 execute()\uac00 \ud638\ucd9c\ub418\uba74, Reciever\uc758 action()\uacfc \uac19\uc740 \ud2b9\uc815 operation\uc744 \ud558\ub3c4\ub85d \ud638\ucd9c\ud55c\ub2e4. Receiver \ub610\ud55c, \uc778\ud130\ud398\uc774\uc2a4\ub9cc \ub178\ucd9c\uc2dc\ud0a4\uace0 \uc774\ub97c Command\uac00 \uc0ac\uc6a9\ud558\uae30 \ub54c\ubb38\uc5d0, Receiver\uac00 Command\uc5d0 \ub300\ud574 \uc54c \ud544\uc694\ub3c4 \uc5c6\ub2e4.<\/p>\n\n\n\n<p>\uc608\ub97c \ub4e4\uc5b4, Qt\uc5d0\uc11c \ubc84\ud2bc(Invoker)\ub97c \ub9cc\ub4e4\uc5c8\ub2e4\uba74, QAction(Command)\ub97c \uc0dd\uc131\ud574\uc11c \ubc84\ud2bc\uc5d0 \ud560\ub2f9\ud574\uc8fc\ub294 \uc791\uc5c5\uc744 Client \ucf54\ub4dc\uc5d0\uc11c \ud558\uac8c\ub41c\ub2e4. Command Pattern\uacfc \uc815\ud655\ud558\uac8c \ub9e4\uce6d\ub418\uc9c0\ub294 \uc54a\uc9c0\ub9cc, Qt\uc758 \uba54\ub274\uad6c\ud604 \ub0b4\uc6a9\uc744 \ucc38\uace0\ud558\uc790\uba74 \ub2e4\uc74c\uacfc \uac19\uc774 \uad6c\ud604\ud55c\ub2e4.<\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers\" data-code-block-pro-font-family=\"Code-Pro-Roboto-Mono.ttf\" style=\"font-size:clamp(14px, .875rem, 21px);font-family:Code-Pro-Roboto-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#adbac7;--cbp-line-number-width:calc(2 * 0.6 * .875rem);line-height:clamp(20px, 1.25rem, 30px);--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#22272e\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"54\" height=\"14\" viewBox=\"0 0 54 14\"><g fill=\"none\" fill-rule=\"evenodd\" transform=\"translate(1 1)\"><circle cx=\"6\" cy=\"6\" r=\"6\" fill=\"#FF5F56\" stroke=\"#E0443E\" stroke-width=\".5\"><\/circle><circle cx=\"26\" cy=\"6\" r=\"6\" fill=\"#FFBD2E\" stroke=\"#DEA123\" stroke-width=\".5\"><\/circle><circle cx=\"46\" cy=\"6\" r=\"6\" fill=\"#27C93F\" stroke=\"#1AAB29\" stroke-width=\".5\"><\/circle><\/g><\/svg><\/span><span role=\"button\" tabindex=\"0\" style=\"color:#adbac7;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><pre class=\"code-block-pro-copy-button-pre\" aria-hidden=\"true\"><textarea class=\"code-block-pro-copy-button-textarea\" tabindex=\"-1\" aria-hidden=\"true\" readonly>...\nmenubar = self.menuBar()\nfilemenu = menubar.addMenu(\"&amp;File\")\n\n# exit action\uc744 \uc0dd\uc131\nexit_action = QAction(QIcon(\"..\/resources\/exit_kr.png\"), \"E&amp;xit\", self)\nexit_action.setShortcut(QKeySequence(Qt.CTRL + Qt.Key_Q))\nexit_action.setStatusTip(\"Exit application window\")\n\n# signal-slot \ubaa8\ub378\uc744 \uc4f0\ubbc0\ub85c reciever\ub85c \ud638\ucd9c\ub420 \uba54\uc18c\ub4dc\uac00 \uc124\uc815\nexit_action.triggered.connect(self.my_exit)\n\n# File \uba54\ub274\uc5d0 \uc11c\ube0c\ud56d\ubaa9\uc73c\ub85c \uc815\uc758\ud55c exit QAction\uc744 \ucd94\uac00\ud55c\ub2e4.\nfilemenu.addAction(exit_action)\n...\n\ndef my_exit(self):\n    print(\"menu exit !!\")\n    QApplication.quit()\n...<\/textarea><\/pre><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki github-dark-dimmed\" style=\"background-color: #22272e\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #6CB6FF\">...<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">menubar <\/span><span style=\"color: #F47067\">=<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #6CB6FF\">self<\/span><span style=\"color: #ADBAC7\">.menuBar()<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">filemenu <\/span><span style=\"color: #F47067\">=<\/span><span style=\"color: #ADBAC7\"> menubar.addMenu(<\/span><span style=\"color: #96D0FF\">&quot;&amp;File&quot;<\/span><span style=\"color: #ADBAC7\">)<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #768390\"># exit action\uc744 \uc0dd\uc131<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">exit_action <\/span><span style=\"color: #F47067\">=<\/span><span style=\"color: #ADBAC7\"> QAction(QIcon(<\/span><span style=\"color: #96D0FF\">&quot;..\/resources\/exit_kr.png&quot;<\/span><span style=\"color: #ADBAC7\">), <\/span><span style=\"color: #96D0FF\">&quot;E&amp;xit&quot;<\/span><span style=\"color: #ADBAC7\">, <\/span><span style=\"color: #6CB6FF\">self<\/span><span style=\"color: #ADBAC7\">)<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">exit_action.setShortcut(QKeySequence(Qt.<\/span><span style=\"color: #6CB6FF\">CTRL<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #F47067\">+<\/span><span style=\"color: #ADBAC7\"> Qt.Key_Q))<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">exit_action.setStatusTip(<\/span><span style=\"color: #96D0FF\">&quot;Exit application window&quot;<\/span><span style=\"color: #ADBAC7\">)<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #768390\"># signal-slot \ubaa8\ub378\uc744 \uc4f0\ubbc0\ub85c reciever\ub85c \ud638\ucd9c\ub420 \uba54\uc18c\ub4dc\uac00 \uc124\uc815<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">exit_action.triggered.connect(<\/span><span style=\"color: #6CB6FF\">self<\/span><span style=\"color: #ADBAC7\">.my_exit)<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #768390\"># File \uba54\ub274\uc5d0 \uc11c\ube0c\ud56d\ubaa9\uc73c\ub85c \uc815\uc758\ud55c exit QAction\uc744 \ucd94\uac00\ud55c\ub2e4.<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">filemenu.addAction(exit_action)<\/span><\/span>\n<span class=\"line\"><span style=\"color: #6CB6FF\">...<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #F47067\">def<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #DCBDFB\">my_exit<\/span><span style=\"color: #ADBAC7\">(self):<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">    <\/span><span style=\"color: #6CB6FF\">print<\/span><span style=\"color: #ADBAC7\">(<\/span><span style=\"color: #96D0FF\">&quot;menu exit !!&quot;<\/span><span style=\"color: #ADBAC7\">)<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">    QApplication.quit()<\/span><\/span>\n<span class=\"line\"><span style=\"color: #6CB6FF\">...<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<p>action\uc758 triggered\uac00 execute\uc5d0 \ud574\ub2f9\ud558\uac8c \ub418\uace0, connect\ub85c \uc0ac\uc6a9\uc790 \uc815\uc758 \uba54\uc18c\ub4dc \uc548\uc5d0\uc11c \uc218\ud589\ud560 \ucf54\ub4dc\ub97c \uc815\uc758\ud558\uac8c \ub41c\ub2e4. <\/p>\n\n\n\n<hr class=\"wp-block-separator has-css-opacity is-style-dots\"\/>\n\n\n\n<p>\uc5b4\ub290\uacf3\uc774\ub098 \ub2e4 \uc801\uc6a9\uac00\ub2a5\ud560\uac70 \uac19\uc9c0\ub9cc, \uc758\uc678\ub85c \uadf8\ub9ac \uac04\ub2e8\ud558\uc9c0\ub294 \uc54a\ub2e4. \ud14d\uc2a4\ud2b8 \uc5d0\ub514\ud130\ub97c \uc0dd\uac01\ud55c\ub2e4\uba74, copy-paste \uc2dc\uc5d0 \ud074\ub9bd\ubcf4\ub4dc\ub97c \uc774\uc6a9\ud574\uc57c\ud55c\ub2e4. undo, redo\ub3c4 \uc9c0\uc6d0\ud574\uc57c \ud558\ubbc0\ub85c, \ucee4\ub9e8\ub4dc\uc5d0 \ubc31\uc5c5\uc6a9 \ubc84\ud37c\uac00 \ud544\uc694\ud558\ub2e4. \uc774\ub97c \uc704\ud574 Memento pattern\uc744 \uc0ac\uc6a9\ud574\uc57c \ud55c\ub2e4. \ub610\ud55c, \ud14d\uc2a4\ud2b8 \uc77c\ubd80\uac00 \uc120\ud0dd\ub41c \uc0c1\ud0dc\ub77c\uba74, \uc0c8\ub85c\uc6b4 \ud14d\uc2a4\ud2b8 \uc785\ub825\uc774\ub098 paste\uc2dc\uc5d0 \uc774 \uc120\ud0dd\ubd80\ubd84\uc744 \ubc31\uc5c5\ud558\uace0 \uc9c0\uc6cc\uc57c \ud55c\ub2e4. \uc0d8\ud50c\ub85c \uad6c\ud604\ud558\ub824\ub2e4\ubcf4\ub2c8 \uc0dd\uac01\ubcf4\ub2e4 \ud544\uc694\ud55c\uac8c \ub9ce\uc544\uc11c \uae30\uac01.<\/p>\n\n\n\n<p>\ube14\ub80c\ub354\ub098 \uadf8\ub798\ud53d \uc5d0\ub514\ud130\uc5d0\uc11c \ub3c4\ud615\uc758 scale, rotate, move\ub4f1\uc744 \uc0d8\ud50c\ub85c \ud574\ubcfc\uae4c\ub3c4 \uc0dd\uac01 \ud588\ub294\ub370, \uac01\uac01\uc5d0 \ub530\ub77c \ub2e4\ub978 \ud30c\ub77c\ubbf8\ud130\uac00 \ud544\uc694\ud574\uc11c \uc801\ud569\ud574 \ubcf4\uc774\uc9c0 \uc54a\uc558\ub2e4. \uc774 \uacbd\uc6b0\uc5d0\ub294 \uc0ac\uc6a9\uc790 \uc785\ub825\uc5d0 \ub530\ub77c Command\uc5d0 parameter\ub97c \uc785\ub825\ud574 \ub3d9\uc801\uc73c\ub85c \uc0dd\uc131\ud558\uace0, \uc785\ub825\uc774 \uc644\ub8cc\ub420 \ub54c, \ud574\ub2f9 Command\ub97c execute\ud558\ub294 \ubc29\uc2dd\uc774 \ub418\uc5b4\uc57c \ud560 \uac83 \uac19\ub2e4.<\/p>\n\n\n\n<p>Command pattern\uacfc \uc720\uc0ac\ud55c \ud615\ud0dc\uc758 \ub514\uc790\uc778\uc740 \ub9ce\uc544\ubcf4\uc774\uc9c0\ub9cc, \uc55e\uc5d0 \uc81c\uc2dc\ud55c UML\uc744 \uadf8\ub300\ub85c \ub530\ub974\ub294 \uac00\uc7a5 \uc801\ud569\ud55c \uc608\ub4e4\uc740 \uc5ed\uc2dc \uba54\ub274\ub098 \ud234\ubc14, \uae30\ud0c0 \ubc84\ud2bc\ud615\ud0dc\uc758 \ucee4\ub9e8\ub4dc\uac00 \ub420\ub4ef\ud558\ub2e4, \ubba4\uc9c1\ud50c\ub808\uc774\uc5b4\uc758 \ubc84\ud2bc\ub4e4\ucc98\ub7fc.<\/p>\n\n\n\n<p>\ub9d0\uc774 \ub098\uc628\uae40\uc5d0, \ubba4\uc9c1\ud50c\ub808\uc774\uc5b4\ub97c \uc608\ub85c\ub4e4\uc5b4\ubcfc\ud150\ub370, play, stop\ub4f1\uc740 \ud2b9\ubcc4\ud55c\uac8c \uc5c6\uc5b4\uc11c playlist\uc5d0 \ub300\ud55c \uc77c\ubd80\ub97c \ub9cc\ub4e4\uc5b4\ubcfc\uae4c \ud55c\ub2e4. playlist\uc5d0\uc120 undo\uae30\ub2a5\uae4c\uc9c0 \ud574\ubcfc \uc218 \uc788\uc744\uac70 \uac19\ub2e4. \uc5ec\uae30\uc11c\ub294 undo\ub97c \uac04\ub2e8\ud55c \uc2a4\ud0dd\uc744 \uc774\uc6a9\ud558\uace0 Memento pattern\uae4c\uc9c0\ub294 \uace0\ub824\ud558\uc9c0 \uc54a\uc558\ub2e4.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Kotlin<\/h3>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers\" data-code-block-pro-font-family=\"Code-Pro-Roboto-Mono.ttf\" style=\"font-size:clamp(14px, .875rem, 21px);font-family:Code-Pro-Roboto-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#adbac7;--cbp-line-number-width:calc(2 * 0.6 * .875rem);line-height:clamp(20px, 1.25rem, 30px);--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#22272e\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"54\" height=\"14\" viewBox=\"0 0 54 14\"><g fill=\"none\" fill-rule=\"evenodd\" transform=\"translate(1 1)\"><circle cx=\"6\" cy=\"6\" r=\"6\" fill=\"#FF5F56\" stroke=\"#E0443E\" stroke-width=\".5\"><\/circle><circle cx=\"26\" cy=\"6\" r=\"6\" fill=\"#FFBD2E\" stroke=\"#DEA123\" stroke-width=\".5\"><\/circle><circle cx=\"46\" cy=\"6\" r=\"6\" fill=\"#27C93F\" stroke=\"#1AAB29\" stroke-width=\".5\"><\/circle><\/g><\/svg><\/span><span role=\"button\" tabindex=\"0\" style=\"color:#adbac7;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><pre class=\"code-block-pro-copy-button-pre\" aria-hidden=\"true\"><textarea class=\"code-block-pro-copy-button-textarea\" tabindex=\"-1\" aria-hidden=\"true\" readonly>package command\n\ninterface StackImplement&lt;T> {\n    fun count(): Int\n    fun pop(): T\n    fun peek(): T\n    fun push(item: T)\n    fun isEmpty(): Boolean\n    fun isNotEmpty(): Boolean\n    fun clear(): Unit\n}\n\nclass Stack&lt;T>: StackImplement&lt;T> {\n    private var list = mutableListOf&lt;T>()\n\n    constructor() {\n        \/\/super()\n    }\n\n    constructor(initialList: List&lt;T>): this() {\n        list = initialList.toMutableList()\n    }\n\n    override fun count(): Int {\n        return list.size\n    }\n\n    override fun pop(): T {\n        return list.removeAt(list.size - 1)\n    }\n\n    override fun peek(): T {\n        return list&#91;list.size - 1&#93;\n    }\n\n    override fun push(item: T) {\n        list.add(item)\n    }\n\n    override fun isEmpty(): Boolean {\n        return list.size == 0\n    }\n\n    override fun isNotEmpty(): Boolean {\n        return list.isNotEmpty()\n    }\n\n    override fun clear(): Unit {\n        list.clear()\n    }\n}<\/textarea><\/pre><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki github-dark-dimmed\" style=\"background-color: #22272e\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #F47067\">package<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #F69D50\">command<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #F47067\">interface<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #F69D50\">StackImplement<\/span><span style=\"color: #ADBAC7\">&lt;<\/span><span style=\"color: #F69D50\">T<\/span><span style=\"color: #ADBAC7\">&gt; {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">    <\/span><span style=\"color: #F47067\">fun<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #DCBDFB\">count<\/span><span style=\"color: #ADBAC7\">(): <\/span><span style=\"color: #F69D50\">Int<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">    <\/span><span style=\"color: #F47067\">fun<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #DCBDFB\">pop<\/span><span style=\"color: #ADBAC7\">(): <\/span><span style=\"color: #F69D50\">T<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">    <\/span><span style=\"color: #F47067\">fun<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #DCBDFB\">peek<\/span><span style=\"color: #ADBAC7\">(): <\/span><span style=\"color: #F69D50\">T<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">    <\/span><span style=\"color: #F47067\">fun<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #DCBDFB\">push<\/span><span style=\"color: #ADBAC7\">(item: <\/span><span style=\"color: #F69D50\">T<\/span><span style=\"color: #ADBAC7\">)<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">    <\/span><span style=\"color: #F47067\">fun<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #DCBDFB\">isEmpty<\/span><span style=\"color: #ADBAC7\">(): <\/span><span style=\"color: #F69D50\">Boolean<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">    <\/span><span style=\"color: #F47067\">fun<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #DCBDFB\">isNotEmpty<\/span><span style=\"color: #ADBAC7\">(): <\/span><span style=\"color: #F69D50\">Boolean<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">    <\/span><span style=\"color: #F47067\">fun<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #DCBDFB\">clear<\/span><span style=\"color: #ADBAC7\">(): <\/span><span style=\"color: #F69D50\">Unit<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">}<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #F47067\">class<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #F69D50\">Stack<\/span><span style=\"color: #ADBAC7\">&lt;<\/span><span style=\"color: #F69D50\">T<\/span><span style=\"color: #ADBAC7\">&gt;: <\/span><span style=\"color: #F69D50\">StackImplement<\/span><span style=\"color: #ADBAC7\">&lt;<\/span><span style=\"color: #F69D50\">T<\/span><span style=\"color: #ADBAC7\">&gt; {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">    <\/span><span style=\"color: #F47067\">private<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #F47067\">var<\/span><span style=\"color: #ADBAC7\"> list <\/span><span style=\"color: #F47067\">=<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #DCBDFB\">mutableListOf<\/span><span style=\"color: #ADBAC7\">&lt;<\/span><span style=\"color: #F69D50\">T<\/span><span style=\"color: #ADBAC7\">&gt;()<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">    <\/span><span style=\"color: #DCBDFB\">constructor<\/span><span style=\"color: #ADBAC7\">() {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">        <\/span><span style=\"color: #768390\">\/\/super()<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">    }<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">    <\/span><span style=\"color: #DCBDFB\">constructor<\/span><span style=\"color: #ADBAC7\">(initialList: <\/span><span style=\"color: #F69D50\">List<\/span><span style=\"color: #ADBAC7\">&lt;<\/span><span style=\"color: #F69D50\">T<\/span><span style=\"color: #ADBAC7\">&gt;): <\/span><span style=\"color: #F69D50\">this<\/span><span style=\"color: #ADBAC7\">() {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">        list <\/span><span style=\"color: #F47067\">=<\/span><span style=\"color: #ADBAC7\"> initialList.<\/span><span style=\"color: #DCBDFB\">toMutableList<\/span><span style=\"color: #ADBAC7\">()<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">    }<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">    <\/span><span style=\"color: #F47067\">override<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #F47067\">fun<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #DCBDFB\">count<\/span><span style=\"color: #ADBAC7\">(): <\/span><span style=\"color: #F69D50\">Int<\/span><span style=\"color: #ADBAC7\"> {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">        <\/span><span style=\"color: #F47067\">return<\/span><span style=\"color: #ADBAC7\"> list.size<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">    }<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">    <\/span><span style=\"color: #F47067\">override<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #F47067\">fun<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #DCBDFB\">pop<\/span><span style=\"color: #ADBAC7\">(): <\/span><span style=\"color: #F69D50\">T<\/span><span style=\"color: #ADBAC7\"> {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">        <\/span><span style=\"color: #F47067\">return<\/span><span style=\"color: #ADBAC7\"> list.<\/span><span style=\"color: #DCBDFB\">removeAt<\/span><span style=\"color: #ADBAC7\">(list.size <\/span><span style=\"color: #F47067\">-<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #6CB6FF\">1<\/span><span style=\"color: #ADBAC7\">)<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">    }<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">    <\/span><span style=\"color: #F47067\">override<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #F47067\">fun<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #DCBDFB\">peek<\/span><span style=\"color: #ADBAC7\">(): <\/span><span style=\"color: #F69D50\">T<\/span><span style=\"color: #ADBAC7\"> {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">        <\/span><span style=\"color: #F47067\">return<\/span><span style=\"color: #ADBAC7\"> list&#91;list.size <\/span><span style=\"color: #F47067\">-<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #6CB6FF\">1<\/span><span style=\"color: #ADBAC7\">&#93;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">    }<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">    <\/span><span style=\"color: #F47067\">override<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #F47067\">fun<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #DCBDFB\">push<\/span><span style=\"color: #ADBAC7\">(item: <\/span><span style=\"color: #F69D50\">T<\/span><span style=\"color: #ADBAC7\">) {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">        list.<\/span><span style=\"color: #DCBDFB\">add<\/span><span style=\"color: #ADBAC7\">(item)<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">    }<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">    <\/span><span style=\"color: #F47067\">override<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #F47067\">fun<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #DCBDFB\">isEmpty<\/span><span style=\"color: #ADBAC7\">(): <\/span><span style=\"color: #F69D50\">Boolean<\/span><span style=\"color: #ADBAC7\"> {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">        <\/span><span style=\"color: #F47067\">return<\/span><span style=\"color: #ADBAC7\"> list.size <\/span><span style=\"color: #F47067\">==<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #6CB6FF\">0<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">    }<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">    <\/span><span style=\"color: #F47067\">override<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #F47067\">fun<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #DCBDFB\">isNotEmpty<\/span><span style=\"color: #ADBAC7\">(): <\/span><span style=\"color: #F69D50\">Boolean<\/span><span style=\"color: #ADBAC7\"> {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">        <\/span><span style=\"color: #F47067\">return<\/span><span style=\"color: #ADBAC7\"> list.<\/span><span style=\"color: #DCBDFB\">isNotEmpty<\/span><span style=\"color: #ADBAC7\">()<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">    }<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">    <\/span><span style=\"color: #F47067\">override<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #F47067\">fun<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #DCBDFB\">clear<\/span><span style=\"color: #ADBAC7\">(): <\/span><span style=\"color: #F69D50\">Unit<\/span><span style=\"color: #ADBAC7\"> {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">        list.<\/span><span style=\"color: #DCBDFB\">clear<\/span><span style=\"color: #ADBAC7\">()<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">    }<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">}<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<p>undo \uae30\ub2a5\uc744 \ud558\ub824\uba74, command\ub97c stack\uc5d0 \uc313\uc544\ub194\uc57c\ud55c\ub2e4. Kotlin\uc5d0 stack\uc774 \uc5c6\uc73c\ubbc0\ub85c \ub530\ub85c \uad6c\ud604\ud588\ub2e4. \ud2b9\ubcc4\ud55c\uac74 \uc5c6\uc73c\ub2c8 \ubc14\ub85c \ub2e4\uc74c \ucf54\ub4dc\ub97c \ubcf4\uc790.<\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers\" data-code-block-pro-font-family=\"Code-Pro-Roboto-Mono.ttf\" style=\"font-size:clamp(14px, .875rem, 21px);font-family:Code-Pro-Roboto-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#adbac7;--cbp-line-number-width:calc(1 * 0.6 * .875rem);line-height:clamp(20px, 1.25rem, 30px);--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#22272e\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"54\" height=\"14\" viewBox=\"0 0 54 14\"><g fill=\"none\" fill-rule=\"evenodd\" transform=\"translate(1 1)\"><circle cx=\"6\" cy=\"6\" r=\"6\" fill=\"#FF5F56\" stroke=\"#E0443E\" stroke-width=\".5\"><\/circle><circle cx=\"26\" cy=\"6\" r=\"6\" fill=\"#FFBD2E\" stroke=\"#DEA123\" stroke-width=\".5\"><\/circle><circle cx=\"46\" cy=\"6\" r=\"6\" fill=\"#27C93F\" stroke=\"#1AAB29\" stroke-width=\".5\"><\/circle><\/g><\/svg><\/span><span role=\"button\" tabindex=\"0\" style=\"color:#adbac7;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><pre class=\"code-block-pro-copy-button-pre\" aria-hidden=\"true\"><textarea class=\"code-block-pro-copy-button-textarea\" tabindex=\"-1\" aria-hidden=\"true\" readonly>package command\n\ninterface ICommand{\n    fun execute()\n    fun undo()\n}<\/textarea><\/pre><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki github-dark-dimmed\" style=\"background-color: #22272e\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #F47067\">package<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #F69D50\">command<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #F47067\">interface<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #F69D50\">ICommand<\/span><span style=\"color: #ADBAC7\">{<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">    <\/span><span style=\"color: #F47067\">fun<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #DCBDFB\">execute<\/span><span style=\"color: #ADBAC7\">()<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">    <\/span><span style=\"color: #F47067\">fun<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #DCBDFB\">undo<\/span><span style=\"color: #ADBAC7\">()<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">}<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<p>Command\uc5d0 \ub300\ud55c \uc778\ud130\ud398\uc774\uc2a4 \uc815\uc758\uc774\ub2e4. Concrete class\ub294 \ub098\uc911\uc5d0 \ub098\uc628\ub2e4. <\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers\" data-code-block-pro-font-family=\"Code-Pro-Roboto-Mono.ttf\" style=\"font-size:clamp(14px, .875rem, 21px);font-family:Code-Pro-Roboto-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#adbac7;--cbp-line-number-width:calc(2 * 0.6 * .875rem);line-height:clamp(20px, 1.25rem, 30px);--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#22272e\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"54\" height=\"14\" viewBox=\"0 0 54 14\"><g fill=\"none\" fill-rule=\"evenodd\" transform=\"translate(1 1)\"><circle cx=\"6\" cy=\"6\" r=\"6\" fill=\"#FF5F56\" stroke=\"#E0443E\" stroke-width=\".5\"><\/circle><circle cx=\"26\" cy=\"6\" r=\"6\" fill=\"#FFBD2E\" stroke=\"#DEA123\" stroke-width=\".5\"><\/circle><circle cx=\"46\" cy=\"6\" r=\"6\" fill=\"#27C93F\" stroke=\"#1AAB29\" stroke-width=\".5\"><\/circle><\/g><\/svg><\/span><span role=\"button\" tabindex=\"0\" style=\"color:#adbac7;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><pre class=\"code-block-pro-copy-button-pre\" aria-hidden=\"true\"><textarea class=\"code-block-pro-copy-button-textarea\" tabindex=\"-1\" aria-hidden=\"true\" readonly>package command\n\nclass CommandStack{\n    private val commandStack = Stack&lt;ICommand>()\n\n    fun pushCmd(cmd:ICommand){\n        commandStack.push(cmd)\n    }\n\n    private fun popCmd(): ICommand?{\n        return if(commandStack.isNotEmpty())\n            commandStack.pop()\n        else\n            null\n    }\n\n    fun undo(){\n        popCmd()?.undo()\n    }\n\n}<\/textarea><\/pre><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki github-dark-dimmed\" style=\"background-color: #22272e\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #F47067\">package<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #F69D50\">command<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #F47067\">class<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #F69D50\">CommandStack<\/span><span style=\"color: #ADBAC7\">{<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">    <\/span><span style=\"color: #F47067\">private<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #F47067\">val<\/span><span style=\"color: #ADBAC7\"> commandStack <\/span><span style=\"color: #F47067\">=<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #DCBDFB\">Stack<\/span><span style=\"color: #ADBAC7\">&lt;<\/span><span style=\"color: #F69D50\">ICommand<\/span><span style=\"color: #ADBAC7\">&gt;()<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">    <\/span><span style=\"color: #F47067\">fun<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #DCBDFB\">pushCmd<\/span><span style=\"color: #ADBAC7\">(cmd:<\/span><span style=\"color: #F69D50\">ICommand<\/span><span style=\"color: #ADBAC7\">){<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">        commandStack.<\/span><span style=\"color: #DCBDFB\">push<\/span><span style=\"color: #ADBAC7\">(cmd)<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">    }<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">    <\/span><span style=\"color: #F47067\">private<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #F47067\">fun<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #DCBDFB\">popCmd<\/span><span style=\"color: #ADBAC7\">(): <\/span><span style=\"color: #F69D50\">ICommand<\/span><span style=\"color: #ADBAC7\">?{<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">        <\/span><span style=\"color: #F47067\">return<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #F47067\">if<\/span><span style=\"color: #ADBAC7\">(commandStack.<\/span><span style=\"color: #DCBDFB\">isNotEmpty<\/span><span style=\"color: #ADBAC7\">())<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">            commandStack.<\/span><span style=\"color: #DCBDFB\">pop<\/span><span style=\"color: #ADBAC7\">()<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">        <\/span><span style=\"color: #F47067\">else<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">            <\/span><span style=\"color: #6CB6FF\">null<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">    }<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">    <\/span><span style=\"color: #F47067\">fun<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #DCBDFB\">undo<\/span><span style=\"color: #ADBAC7\">(){<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">        <\/span><span style=\"color: #DCBDFB\">popCmd<\/span><span style=\"color: #ADBAC7\">()?.<\/span><span style=\"color: #DCBDFB\">undo<\/span><span style=\"color: #ADBAC7\">()<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">    }<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">}<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<p>command\ub97c \uc800\uc7a5\ud558\ub294 stack\uc758 \uad6c\ud604\uc774\ub2e4. \uadf8\ub0e5 stack\uc774\uc9c0\ub9cc, undo\uac00 \ucd94\uac00\ub418\uc5c8\ub2e4. <\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers\" data-code-block-pro-font-family=\"Code-Pro-Roboto-Mono.ttf\" style=\"font-size:clamp(14px, .875rem, 21px);font-family:Code-Pro-Roboto-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#adbac7;--cbp-line-number-width:calc(2 * 0.6 * .875rem);line-height:clamp(20px, 1.25rem, 30px);--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#22272e\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"54\" height=\"14\" viewBox=\"0 0 54 14\"><g fill=\"none\" fill-rule=\"evenodd\" transform=\"translate(1 1)\"><circle cx=\"6\" cy=\"6\" r=\"6\" fill=\"#FF5F56\" stroke=\"#E0443E\" stroke-width=\".5\"><\/circle><circle cx=\"26\" cy=\"6\" r=\"6\" fill=\"#FFBD2E\" stroke=\"#DEA123\" stroke-width=\".5\"><\/circle><circle cx=\"46\" cy=\"6\" r=\"6\" fill=\"#27C93F\" stroke=\"#1AAB29\" stroke-width=\".5\"><\/circle><\/g><\/svg><\/span><span role=\"button\" tabindex=\"0\" style=\"color:#adbac7;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><pre class=\"code-block-pro-copy-button-pre\" aria-hidden=\"true\"><textarea class=\"code-block-pro-copy-button-textarea\" tabindex=\"-1\" aria-hidden=\"true\" readonly>package command\n\nclass DummyButton(val buttonName: String){\n    private var command: ICommand? = null\n\n    fun assignCommand(cmd: ICommand){\n        command = cmd\n    }\n\n    fun pressed(){\n        command?.execute()\n    }\n}<\/textarea><\/pre><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki github-dark-dimmed\" style=\"background-color: #22272e\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #F47067\">package<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #F69D50\">command<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #F47067\">class<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #F69D50\">DummyButton<\/span><span style=\"color: #ADBAC7\">(<\/span><span style=\"color: #F47067\">val<\/span><span style=\"color: #ADBAC7\"> buttonName: <\/span><span style=\"color: #F69D50\">String<\/span><span style=\"color: #ADBAC7\">){<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">    <\/span><span style=\"color: #F47067\">private<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #F47067\">var<\/span><span style=\"color: #ADBAC7\"> command: <\/span><span style=\"color: #F69D50\">ICommand<\/span><span style=\"color: #ADBAC7\">? <\/span><span style=\"color: #F47067\">=<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #6CB6FF\">null<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">    <\/span><span style=\"color: #F47067\">fun<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #DCBDFB\">assignCommand<\/span><span style=\"color: #ADBAC7\">(cmd: <\/span><span style=\"color: #F69D50\">ICommand<\/span><span style=\"color: #ADBAC7\">){<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">        command <\/span><span style=\"color: #F47067\">=<\/span><span style=\"color: #ADBAC7\"> cmd<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">    }<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">    <\/span><span style=\"color: #F47067\">fun<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #DCBDFB\">pressed<\/span><span style=\"color: #ADBAC7\">(){<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">        command?.<\/span><span style=\"color: #DCBDFB\">execute<\/span><span style=\"color: #ADBAC7\">()<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">    }<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">}<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<p>\ubc84\ud2bc\uc744 \uac00\uc0c1\uc73c\ub85c \uad6c\ud604\ud588\ub2e4. \ubc84\ud2bc\uc774 \ub20c\ub838\uc744 \ub54c, \uc2e4\ud589\ub418\ub294 \ub0b4\uc6a9\uc740 \ubaa8\ub974\uace0 \uc8fc\uc5b4\uc9c4 ICommand \ud074\ub798\uc2a4\uc758 execute()\ub97c \ud638\ucd9c\ud558\uc5ec \uc2e4\ud589\ud560 \ub0b4\uc6a9\uc744 \uc704\uc784\ud55c\ub2e4.<\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers\" data-code-block-pro-font-family=\"Code-Pro-Roboto-Mono.ttf\" style=\"font-size:clamp(14px, .875rem, 21px);font-family:Code-Pro-Roboto-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#adbac7;--cbp-line-number-width:calc(2 * 0.6 * .875rem);line-height:clamp(20px, 1.25rem, 30px);--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#22272e\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"54\" height=\"14\" viewBox=\"0 0 54 14\"><g fill=\"none\" fill-rule=\"evenodd\" transform=\"translate(1 1)\"><circle cx=\"6\" cy=\"6\" r=\"6\" fill=\"#FF5F56\" stroke=\"#E0443E\" stroke-width=\".5\"><\/circle><circle cx=\"26\" cy=\"6\" r=\"6\" fill=\"#FFBD2E\" stroke=\"#DEA123\" stroke-width=\".5\"><\/circle><circle cx=\"46\" cy=\"6\" r=\"6\" fill=\"#27C93F\" stroke=\"#1AAB29\" stroke-width=\".5\"><\/circle><\/g><\/svg><\/span><span role=\"button\" tabindex=\"0\" style=\"color:#adbac7;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><pre class=\"code-block-pro-copy-button-pre\" aria-hidden=\"true\"><textarea class=\"code-block-pro-copy-button-textarea\" tabindex=\"-1\" aria-hidden=\"true\" readonly>package command\n\nclass DummyMusicPlayer{\n    private val playlist = mutableListOf&lt;String>()\n    var selectedIdx = 0\n\n    fun getPlaylist(): List&lt;String>{\n        return playlist.toList()\n    }\n\n    fun clearPlaylist(){\n        playlist.clear()\n    }\n\n    fun append(song: String): Int{\n        playlist.add(song)\n        return playlist.count() - 1\n    }\n\n    fun insert(idx: Int, song: String){\n        playlist.add(idx, song)\n    }\n\n    fun delete(idx: Int = -1): String{\n        return if(idx == -1)\n            playlist.removeAt(selectedIdx)\n        else\n            playlist.removeAt(idx)\n    }\n}<\/textarea><\/pre><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki github-dark-dimmed\" style=\"background-color: #22272e\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #F47067\">package<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #F69D50\">command<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #F47067\">class<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #F69D50\">DummyMusicPlayer<\/span><span style=\"color: #ADBAC7\">{<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">    <\/span><span style=\"color: #F47067\">private<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #F47067\">val<\/span><span style=\"color: #ADBAC7\"> playlist <\/span><span style=\"color: #F47067\">=<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #DCBDFB\">mutableListOf<\/span><span style=\"color: #ADBAC7\">&lt;<\/span><span style=\"color: #F69D50\">String<\/span><span style=\"color: #ADBAC7\">&gt;()<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">    <\/span><span style=\"color: #F47067\">var<\/span><span style=\"color: #ADBAC7\"> selectedIdx <\/span><span style=\"color: #F47067\">=<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #6CB6FF\">0<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">    <\/span><span style=\"color: #F47067\">fun<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #DCBDFB\">getPlaylist<\/span><span style=\"color: #ADBAC7\">(): <\/span><span style=\"color: #F69D50\">List<\/span><span style=\"color: #ADBAC7\">&lt;<\/span><span style=\"color: #F69D50\">String<\/span><span style=\"color: #ADBAC7\">&gt;{<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">        <\/span><span style=\"color: #F47067\">return<\/span><span style=\"color: #ADBAC7\"> playlist.<\/span><span style=\"color: #DCBDFB\">toList<\/span><span style=\"color: #ADBAC7\">()<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">    }<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">    <\/span><span style=\"color: #F47067\">fun<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #DCBDFB\">clearPlaylist<\/span><span style=\"color: #ADBAC7\">(){<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">        playlist.<\/span><span style=\"color: #DCBDFB\">clear<\/span><span style=\"color: #ADBAC7\">()<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">    }<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">    <\/span><span style=\"color: #F47067\">fun<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #DCBDFB\">append<\/span><span style=\"color: #ADBAC7\">(song: <\/span><span style=\"color: #F69D50\">String<\/span><span style=\"color: #ADBAC7\">): <\/span><span style=\"color: #F69D50\">Int<\/span><span style=\"color: #ADBAC7\">{<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">        playlist.<\/span><span style=\"color: #DCBDFB\">add<\/span><span style=\"color: #ADBAC7\">(song)<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">        <\/span><span style=\"color: #F47067\">return<\/span><span style=\"color: #ADBAC7\"> playlist.<\/span><span style=\"color: #DCBDFB\">count<\/span><span style=\"color: #ADBAC7\">() <\/span><span style=\"color: #F47067\">-<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #6CB6FF\">1<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">    }<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">    <\/span><span style=\"color: #F47067\">fun<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #DCBDFB\">insert<\/span><span style=\"color: #ADBAC7\">(idx: <\/span><span style=\"color: #F69D50\">Int<\/span><span style=\"color: #ADBAC7\">, song: <\/span><span style=\"color: #F69D50\">String<\/span><span style=\"color: #ADBAC7\">){<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">        playlist.<\/span><span style=\"color: #DCBDFB\">add<\/span><span style=\"color: #ADBAC7\">(idx, song)<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">    }<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">    <\/span><span style=\"color: #F47067\">fun<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #DCBDFB\">delete<\/span><span style=\"color: #ADBAC7\">(idx: <\/span><span style=\"color: #F69D50\">Int<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #F47067\">=<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #F47067\">-<\/span><span style=\"color: #6CB6FF\">1<\/span><span style=\"color: #ADBAC7\">): <\/span><span style=\"color: #F69D50\">String<\/span><span style=\"color: #ADBAC7\">{<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">        <\/span><span style=\"color: #F47067\">return<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #F47067\">if<\/span><span style=\"color: #ADBAC7\">(idx <\/span><span style=\"color: #F47067\">==<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #F47067\">-<\/span><span style=\"color: #6CB6FF\">1<\/span><span style=\"color: #ADBAC7\">)<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">            playlist.<\/span><span style=\"color: #DCBDFB\">removeAt<\/span><span style=\"color: #ADBAC7\">(selectedIdx)<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">        <\/span><span style=\"color: #F47067\">else<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">            playlist.<\/span><span style=\"color: #DCBDFB\">removeAt<\/span><span style=\"color: #ADBAC7\">(idx)<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">    }<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">}<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<p>command \ud074\ub798\uc2a4\uc5d0\uc11c \uc0ac\uc6a9\ud560 \uae30\ub2a5\ub9cc \uc77c\ubd80 \uad6c\ud604\ub41c \ubba4\uc9c1 \ud50c\ub808\uc774\uc5b4 \ud074\ub798\uc2a4\ub2e4. playlist\uc5d0 \ub300\ud55c \uc77c\ubd80\ubd84\ub9cc \uad6c\ud604\ub418\uc5b4 \uc788\ub2e4. <\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers\" data-code-block-pro-font-family=\"Code-Pro-Roboto-Mono.ttf\" style=\"font-size:clamp(14px, .875rem, 21px);font-family:Code-Pro-Roboto-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#adbac7;--cbp-line-number-width:calc(2 * 0.6 * .875rem);line-height:clamp(20px, 1.25rem, 30px);--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#22272e\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"54\" height=\"14\" viewBox=\"0 0 54 14\"><g fill=\"none\" fill-rule=\"evenodd\" transform=\"translate(1 1)\"><circle cx=\"6\" cy=\"6\" r=\"6\" fill=\"#FF5F56\" stroke=\"#E0443E\" stroke-width=\".5\"><\/circle><circle cx=\"26\" cy=\"6\" r=\"6\" fill=\"#FFBD2E\" stroke=\"#DEA123\" stroke-width=\".5\"><\/circle><circle cx=\"46\" cy=\"6\" r=\"6\" fill=\"#27C93F\" stroke=\"#1AAB29\" stroke-width=\".5\"><\/circle><\/g><\/svg><\/span><span role=\"button\" tabindex=\"0\" style=\"color:#adbac7;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><pre class=\"code-block-pro-copy-button-pre\" aria-hidden=\"true\"><textarea class=\"code-block-pro-copy-button-textarea\" tabindex=\"-1\" aria-hidden=\"true\" readonly>package command\n\nclass ShuffleCommand(private val receiver: DummyMusicPlayer, private val undoStack: CommandStack):ICommand{\n    private var playlistBackup: List&lt;String> = listOf&lt;String>()\n    override fun execute() {\n        playlistBackup = receiver.getPlaylist()\n        receiver.clearPlaylist()\n        for(song in playlistBackup.shuffled()){\n            receiver.append(song)\n        }\n\n        val cmd = ShuffleCommand(receiver, undoStack)\n        cmd.playlistBackup = playlistBackup.toList()\n        undoStack.pushCmd(cmd)\n    }\n\n    override fun undo() {\n        if(playlistBackup.count() > 0){\n            receiver.clearPlaylist()\n            for(song in playlistBackup){\n                receiver.append(song)\n            }\n        }\n    }\n}\n\nclass AppendCommand(private val receiver: DummyMusicPlayer, private val undoStack: CommandStack):ICommand{\n    private var idx = -1\n    override fun execute() {\n        val song = callFileOpenDialog()\n        idx = receiver.append(song)\n\n        val cmd = AppendCommand(receiver, undoStack)\n        cmd.idx = idx\n        undoStack.pushCmd(cmd)\n    }\n\n    override fun undo() {\n        if(idx != -1){\n            receiver.delete(idx)\n        }\n    }\n\n    \/\/ only for test. emulate FileOpenDialog\n    companion object DummyFileOpenDialog{\n        private val testSongs = arrayOf(\"song1\", \"song2\", \"song3\", \"song4\", \"song5\")\n        private var fileOpenIdx = 0\n\n        private fun callFileOpenDialog(): String{\n            \/\/ Mockup for file open dialog\n            val song = testSongs&#91;fileOpenIdx&#93;\n            fileOpenIdx++\n            if(fileOpenIdx >= testSongs.count()) fileOpenIdx = 0\n\n            return song\n        }\n    }\n}\n\nclass DeleteCommand(private val receiver: DummyMusicPlayer, private val undoStack: CommandStack):ICommand{\n    private var song: String = \"\"\n    private var idx = -1\n\n    override fun execute() {\n        idx = receiver.selectedIdx\n        song = receiver.delete()\n\n        val cmd = DeleteCommand(receiver, undoStack)\n        cmd.song = song\n        cmd.idx = idx\n        undoStack.pushCmd(cmd)\n    }\n\n    override fun undo() {\n        if(idx != -1){\n            receiver.insert(idx, song)\n        }\n    }\n\n}<\/textarea><\/pre><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki github-dark-dimmed\" style=\"background-color: #22272e\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #F47067\">package<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #F69D50\">command<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #F47067\">class<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #F69D50\">ShuffleCommand<\/span><span style=\"color: #ADBAC7\">(<\/span><span style=\"color: #F47067\">private<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #F47067\">val<\/span><span style=\"color: #ADBAC7\"> receiver: <\/span><span style=\"color: #F69D50\">DummyMusicPlayer<\/span><span style=\"color: #ADBAC7\">, <\/span><span style=\"color: #F47067\">private<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #F47067\">val<\/span><span style=\"color: #ADBAC7\"> undoStack: <\/span><span style=\"color: #F69D50\">CommandStack<\/span><span style=\"color: #ADBAC7\">):<\/span><span style=\"color: #F69D50\">ICommand<\/span><span style=\"color: #ADBAC7\">{<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">    <\/span><span style=\"color: #F47067\">private<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #F47067\">var<\/span><span style=\"color: #ADBAC7\"> playlistBackup: <\/span><span style=\"color: #F69D50\">List<\/span><span style=\"color: #ADBAC7\">&lt;<\/span><span style=\"color: #F69D50\">String<\/span><span style=\"color: #ADBAC7\">&gt; <\/span><span style=\"color: #F47067\">=<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #DCBDFB\">listOf<\/span><span style=\"color: #ADBAC7\">&lt;<\/span><span style=\"color: #F69D50\">String<\/span><span style=\"color: #ADBAC7\">&gt;()<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">    <\/span><span style=\"color: #F47067\">override<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #F47067\">fun<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #DCBDFB\">execute<\/span><span style=\"color: #ADBAC7\">() {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">        playlistBackup <\/span><span style=\"color: #F47067\">=<\/span><span style=\"color: #ADBAC7\"> receiver.<\/span><span style=\"color: #DCBDFB\">getPlaylist<\/span><span style=\"color: #ADBAC7\">()<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">        receiver.<\/span><span style=\"color: #DCBDFB\">clearPlaylist<\/span><span style=\"color: #ADBAC7\">()<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">        <\/span><span style=\"color: #F47067\">for<\/span><span style=\"color: #ADBAC7\">(song <\/span><span style=\"color: #F47067\">in<\/span><span style=\"color: #ADBAC7\"> playlistBackup.<\/span><span style=\"color: #DCBDFB\">shuffled<\/span><span style=\"color: #ADBAC7\">()){<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">            receiver.<\/span><span style=\"color: #DCBDFB\">append<\/span><span style=\"color: #ADBAC7\">(song)<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">        }<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">        <\/span><span style=\"color: #F47067\">val<\/span><span style=\"color: #ADBAC7\"> cmd <\/span><span style=\"color: #F47067\">=<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #DCBDFB\">ShuffleCommand<\/span><span style=\"color: #ADBAC7\">(receiver, undoStack)<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">        cmd.playlistBackup <\/span><span style=\"color: #F47067\">=<\/span><span style=\"color: #ADBAC7\"> playlistBackup.<\/span><span style=\"color: #DCBDFB\">toList<\/span><span style=\"color: #ADBAC7\">()<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">        undoStack.<\/span><span style=\"color: #DCBDFB\">pushCmd<\/span><span style=\"color: #ADBAC7\">(cmd)<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">    }<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">    <\/span><span style=\"color: #F47067\">override<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #F47067\">fun<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #DCBDFB\">undo<\/span><span style=\"color: #ADBAC7\">() {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">        <\/span><span style=\"color: #F47067\">if<\/span><span style=\"color: #ADBAC7\">(playlistBackup.<\/span><span style=\"color: #DCBDFB\">count<\/span><span style=\"color: #ADBAC7\">() <\/span><span style=\"color: #F47067\">&gt;<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #6CB6FF\">0<\/span><span style=\"color: #ADBAC7\">){<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">            receiver.<\/span><span style=\"color: #DCBDFB\">clearPlaylist<\/span><span style=\"color: #ADBAC7\">()<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">            <\/span><span style=\"color: #F47067\">for<\/span><span style=\"color: #ADBAC7\">(song <\/span><span style=\"color: #F47067\">in<\/span><span style=\"color: #ADBAC7\"> playlistBackup){<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">                receiver.<\/span><span style=\"color: #DCBDFB\">append<\/span><span style=\"color: #ADBAC7\">(song)<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">            }<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">        }<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">    }<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">}<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #F47067\">class<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #F69D50\">AppendCommand<\/span><span style=\"color: #ADBAC7\">(<\/span><span style=\"color: #F47067\">private<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #F47067\">val<\/span><span style=\"color: #ADBAC7\"> receiver: <\/span><span style=\"color: #F69D50\">DummyMusicPlayer<\/span><span style=\"color: #ADBAC7\">, <\/span><span style=\"color: #F47067\">private<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #F47067\">val<\/span><span style=\"color: #ADBAC7\"> undoStack: <\/span><span style=\"color: #F69D50\">CommandStack<\/span><span style=\"color: #ADBAC7\">):<\/span><span style=\"color: #F69D50\">ICommand<\/span><span style=\"color: #ADBAC7\">{<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">    <\/span><span style=\"color: #F47067\">private<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #F47067\">var<\/span><span style=\"color: #ADBAC7\"> idx <\/span><span style=\"color: #F47067\">=<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #F47067\">-<\/span><span style=\"color: #6CB6FF\">1<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">    <\/span><span style=\"color: #F47067\">override<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #F47067\">fun<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #DCBDFB\">execute<\/span><span style=\"color: #ADBAC7\">() {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">        <\/span><span style=\"color: #F47067\">val<\/span><span style=\"color: #ADBAC7\"> song <\/span><span style=\"color: #F47067\">=<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #DCBDFB\">callFileOpenDialog<\/span><span style=\"color: #ADBAC7\">()<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">        idx <\/span><span style=\"color: #F47067\">=<\/span><span style=\"color: #ADBAC7\"> receiver.<\/span><span style=\"color: #DCBDFB\">append<\/span><span style=\"color: #ADBAC7\">(song)<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">        <\/span><span style=\"color: #F47067\">val<\/span><span style=\"color: #ADBAC7\"> cmd <\/span><span style=\"color: #F47067\">=<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #DCBDFB\">AppendCommand<\/span><span style=\"color: #ADBAC7\">(receiver, undoStack)<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">        cmd.idx <\/span><span style=\"color: #F47067\">=<\/span><span style=\"color: #ADBAC7\"> idx<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">        undoStack.<\/span><span style=\"color: #DCBDFB\">pushCmd<\/span><span style=\"color: #ADBAC7\">(cmd)<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">    }<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">    <\/span><span style=\"color: #F47067\">override<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #F47067\">fun<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #DCBDFB\">undo<\/span><span style=\"color: #ADBAC7\">() {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">        <\/span><span style=\"color: #F47067\">if<\/span><span style=\"color: #ADBAC7\">(idx <\/span><span style=\"color: #F47067\">!=<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #F47067\">-<\/span><span style=\"color: #6CB6FF\">1<\/span><span style=\"color: #ADBAC7\">){<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">            receiver.<\/span><span style=\"color: #DCBDFB\">delete<\/span><span style=\"color: #ADBAC7\">(idx)<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">        }<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">    }<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">    <\/span><span style=\"color: #768390\">\/\/ only for test. emulate FileOpenDialog<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">    <\/span><span style=\"color: #F47067\">companion<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #F47067\">object<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #F69D50\">DummyFileOpenDialog<\/span><span style=\"color: #ADBAC7\">{<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">        <\/span><span style=\"color: #F47067\">private<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #F47067\">val<\/span><span style=\"color: #ADBAC7\"> testSongs <\/span><span style=\"color: #F47067\">=<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #DCBDFB\">arrayOf<\/span><span style=\"color: #ADBAC7\">(<\/span><span style=\"color: #96D0FF\">&quot;song1&quot;<\/span><span style=\"color: #ADBAC7\">, <\/span><span style=\"color: #96D0FF\">&quot;song2&quot;<\/span><span style=\"color: #ADBAC7\">, <\/span><span style=\"color: #96D0FF\">&quot;song3&quot;<\/span><span style=\"color: #ADBAC7\">, <\/span><span style=\"color: #96D0FF\">&quot;song4&quot;<\/span><span style=\"color: #ADBAC7\">, <\/span><span style=\"color: #96D0FF\">&quot;song5&quot;<\/span><span style=\"color: #ADBAC7\">)<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">        <\/span><span style=\"color: #F47067\">private<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #F47067\">var<\/span><span style=\"color: #ADBAC7\"> fileOpenIdx <\/span><span style=\"color: #F47067\">=<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #6CB6FF\">0<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">        <\/span><span style=\"color: #F47067\">private<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #F47067\">fun<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #DCBDFB\">callFileOpenDialog<\/span><span style=\"color: #ADBAC7\">(): <\/span><span style=\"color: #F69D50\">String<\/span><span style=\"color: #ADBAC7\">{<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">            <\/span><span style=\"color: #768390\">\/\/ Mockup for file open dialog<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">            <\/span><span style=\"color: #F47067\">val<\/span><span style=\"color: #ADBAC7\"> song <\/span><span style=\"color: #F47067\">=<\/span><span style=\"color: #ADBAC7\"> testSongs&#91;fileOpenIdx&#93;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">            fileOpenIdx<\/span><span style=\"color: #F47067\">++<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">            <\/span><span style=\"color: #F47067\">if<\/span><span style=\"color: #ADBAC7\">(fileOpenIdx <\/span><span style=\"color: #F47067\">&gt;=<\/span><span style=\"color: #ADBAC7\"> testSongs.<\/span><span style=\"color: #DCBDFB\">count<\/span><span style=\"color: #ADBAC7\">()) fileOpenIdx <\/span><span style=\"color: #F47067\">=<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #6CB6FF\">0<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">            <\/span><span style=\"color: #F47067\">return<\/span><span style=\"color: #ADBAC7\"> song<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">        }<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">    }<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">}<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #F47067\">class<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #F69D50\">DeleteCommand<\/span><span style=\"color: #ADBAC7\">(<\/span><span style=\"color: #F47067\">private<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #F47067\">val<\/span><span style=\"color: #ADBAC7\"> receiver: <\/span><span style=\"color: #F69D50\">DummyMusicPlayer<\/span><span style=\"color: #ADBAC7\">, <\/span><span style=\"color: #F47067\">private<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #F47067\">val<\/span><span style=\"color: #ADBAC7\"> undoStack: <\/span><span style=\"color: #F69D50\">CommandStack<\/span><span style=\"color: #ADBAC7\">):<\/span><span style=\"color: #F69D50\">ICommand<\/span><span style=\"color: #ADBAC7\">{<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">    <\/span><span style=\"color: #F47067\">private<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #F47067\">var<\/span><span style=\"color: #ADBAC7\"> song: <\/span><span style=\"color: #F69D50\">String<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #F47067\">=<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #96D0FF\">&quot;&quot;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">    <\/span><span style=\"color: #F47067\">private<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #F47067\">var<\/span><span style=\"color: #ADBAC7\"> idx <\/span><span style=\"color: #F47067\">=<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #F47067\">-<\/span><span style=\"color: #6CB6FF\">1<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">    <\/span><span style=\"color: #F47067\">override<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #F47067\">fun<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #DCBDFB\">execute<\/span><span style=\"color: #ADBAC7\">() {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">        idx <\/span><span style=\"color: #F47067\">=<\/span><span style=\"color: #ADBAC7\"> receiver.selectedIdx<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">        song <\/span><span style=\"color: #F47067\">=<\/span><span style=\"color: #ADBAC7\"> receiver.<\/span><span style=\"color: #DCBDFB\">delete<\/span><span style=\"color: #ADBAC7\">()<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">        <\/span><span style=\"color: #F47067\">val<\/span><span style=\"color: #ADBAC7\"> cmd <\/span><span style=\"color: #F47067\">=<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #DCBDFB\">DeleteCommand<\/span><span style=\"color: #ADBAC7\">(receiver, undoStack)<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">        cmd.song <\/span><span style=\"color: #F47067\">=<\/span><span style=\"color: #ADBAC7\"> song<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">        cmd.idx <\/span><span style=\"color: #F47067\">=<\/span><span style=\"color: #ADBAC7\"> idx<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">        undoStack.<\/span><span style=\"color: #DCBDFB\">pushCmd<\/span><span style=\"color: #ADBAC7\">(cmd)<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">    }<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">    <\/span><span style=\"color: #F47067\">override<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #F47067\">fun<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #DCBDFB\">undo<\/span><span style=\"color: #ADBAC7\">() {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">        <\/span><span style=\"color: #F47067\">if<\/span><span style=\"color: #ADBAC7\">(idx <\/span><span style=\"color: #F47067\">!=<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #F47067\">-<\/span><span style=\"color: #6CB6FF\">1<\/span><span style=\"color: #ADBAC7\">){<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">            receiver.<\/span><span style=\"color: #DCBDFB\">insert<\/span><span style=\"color: #ADBAC7\">(idx, song)<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">        }<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">    }<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">}<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<p>\ub2e8\uc9c0 3\uac1c\uc758 \ucee4\ub9e8\ub4dc shuffle, append, delete \ub9cc \uad6c\ud604\ud588\ub294\ub370 \uae38\uc5b4\uc84c\ub2e4. \uc778\ud130\ud398\uc774\uc2a4\uc5d0\ub294 execute()\uc678\uc5d0 undo()\uac00 \ucd94\uac00\ub418\uc5b4 \uc788\ub2e4. \ud074\ub77c\uc774\uc5b8\ud2b8 \uad6c\ud604\uc744 \ubcf4\uace0 \uc790\uc138\ud55c \ub0b4\uc6a9\uc744 \uc0b4\ud3b4\ubcf4\uc790.<\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers\" data-code-block-pro-font-family=\"Code-Pro-Roboto-Mono.ttf\" style=\"font-size:clamp(14px, .875rem, 21px);font-family:Code-Pro-Roboto-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#adbac7;--cbp-line-number-width:calc(2 * 0.6 * .875rem);line-height:clamp(20px, 1.25rem, 30px);--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#22272e\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"54\" height=\"14\" viewBox=\"0 0 54 14\"><g fill=\"none\" fill-rule=\"evenodd\" transform=\"translate(1 1)\"><circle cx=\"6\" cy=\"6\" r=\"6\" fill=\"#FF5F56\" stroke=\"#E0443E\" stroke-width=\".5\"><\/circle><circle cx=\"26\" cy=\"6\" r=\"6\" fill=\"#FFBD2E\" stroke=\"#DEA123\" stroke-width=\".5\"><\/circle><circle cx=\"46\" cy=\"6\" r=\"6\" fill=\"#27C93F\" stroke=\"#1AAB29\" stroke-width=\".5\"><\/circle><\/g><\/svg><\/span><span role=\"button\" tabindex=\"0\" style=\"color:#adbac7;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><pre class=\"code-block-pro-copy-button-pre\" aria-hidden=\"true\"><textarea class=\"code-block-pro-copy-button-textarea\" tabindex=\"-1\" aria-hidden=\"true\" readonly>package command\n\nfun main(args: Array&lt;String>) {\n    \/\/ make instance of receiver\n    val musicPlayer = DummyMusicPlayer()\n\n    \/\/ make commands\n    val addCmd: ICommand = AppendCommand(musicPlayer)\n    val delCmd: ICommand = DeleteCommand(musicPlayer)\n    val shuffleCmd: ICommand = ShuffleCommand(musicPlayer)\n\n    \/\/ make buttons and assign commands\n    val addButton = DummyButton(\"ADD\")\n    addButton.assignCommand(addCmd)\n    val deleteButton = DummyButton(\"DELETE\")\n    deleteButton.assignCommand(delCmd)\n    val shuffleButton = DummyButton(\"SHUFFLE\")\n    shuffleButton.assignCommand(shuffleCmd)\n\n    \/\/ test code\n    addButton.pressed()\n    addButton.pressed()\n    addButton.pressed()\n    addButton.pressed()\n    addButton.pressed()\n    println(\"add test\")\n    println(musicPlayer.getPlaylist())\n\n    shuffleButton.pressed()\n    println(\"shuffle test\")\n    println(musicPlayer.getPlaylist())\n\n    musicPlayer.selectedIdx = 3\n    deleteButton.pressed()\n    musicPlayer.selectedIdx = 0\n    deleteButton.pressed()\n    println(\"delete test\")\n    println(musicPlayer.getPlaylist())\n\n    println(\"undo test\")\n    musicPlayer.undo()\n    println(musicPlayer.getPlaylist())\n    musicPlayer.undo()\n    println(musicPlayer.getPlaylist())\n    musicPlayer.undo()\n    println(musicPlayer.getPlaylist())\n    musicPlayer.undo()\n    println(musicPlayer.getPlaylist())\n    musicPlayer.undo()\n    println(musicPlayer.getPlaylist())\n\n}<\/textarea><\/pre><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki github-dark-dimmed\" style=\"background-color: #22272e\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #F47067\">package<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #F69D50\">command<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #F47067\">fun<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #DCBDFB\">main<\/span><span style=\"color: #ADBAC7\">(args: <\/span><span style=\"color: #F69D50\">Array<\/span><span style=\"color: #ADBAC7\">&lt;<\/span><span style=\"color: #F69D50\">String<\/span><span style=\"color: #ADBAC7\">&gt;) {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">    <\/span><span style=\"color: #768390\">\/\/ make instance of receiver<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">    <\/span><span style=\"color: #F47067\">val<\/span><span style=\"color: #ADBAC7\"> musicPlayer <\/span><span style=\"color: #F47067\">=<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #DCBDFB\">DummyMusicPlayer<\/span><span style=\"color: #ADBAC7\">()<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">    <\/span><span style=\"color: #768390\">\/\/ make commands<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">    <\/span><span style=\"color: #F47067\">val<\/span><span style=\"color: #ADBAC7\"> addCmd: <\/span><span style=\"color: #F69D50\">ICommand<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #F47067\">=<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #DCBDFB\">AppendCommand<\/span><span style=\"color: #ADBAC7\">(musicPlayer)<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">    <\/span><span style=\"color: #F47067\">val<\/span><span style=\"color: #ADBAC7\"> delCmd: <\/span><span style=\"color: #F69D50\">ICommand<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #F47067\">=<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #DCBDFB\">DeleteCommand<\/span><span style=\"color: #ADBAC7\">(musicPlayer)<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">    <\/span><span style=\"color: #F47067\">val<\/span><span style=\"color: #ADBAC7\"> shuffleCmd: <\/span><span style=\"color: #F69D50\">ICommand<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #F47067\">=<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #DCBDFB\">ShuffleCommand<\/span><span style=\"color: #ADBAC7\">(musicPlayer)<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">    <\/span><span style=\"color: #768390\">\/\/ make buttons and assign commands<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">    <\/span><span style=\"color: #F47067\">val<\/span><span style=\"color: #ADBAC7\"> addButton <\/span><span style=\"color: #F47067\">=<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #DCBDFB\">DummyButton<\/span><span style=\"color: #ADBAC7\">(<\/span><span style=\"color: #96D0FF\">&quot;ADD&quot;<\/span><span style=\"color: #ADBAC7\">)<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">    addButton.<\/span><span style=\"color: #DCBDFB\">assignCommand<\/span><span style=\"color: #ADBAC7\">(addCmd)<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">    <\/span><span style=\"color: #F47067\">val<\/span><span style=\"color: #ADBAC7\"> deleteButton <\/span><span style=\"color: #F47067\">=<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #DCBDFB\">DummyButton<\/span><span style=\"color: #ADBAC7\">(<\/span><span style=\"color: #96D0FF\">&quot;DELETE&quot;<\/span><span style=\"color: #ADBAC7\">)<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">    deleteButton.<\/span><span style=\"color: #DCBDFB\">assignCommand<\/span><span style=\"color: #ADBAC7\">(delCmd)<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">    <\/span><span style=\"color: #F47067\">val<\/span><span style=\"color: #ADBAC7\"> shuffleButton <\/span><span style=\"color: #F47067\">=<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #DCBDFB\">DummyButton<\/span><span style=\"color: #ADBAC7\">(<\/span><span style=\"color: #96D0FF\">&quot;SHUFFLE&quot;<\/span><span style=\"color: #ADBAC7\">)<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">    shuffleButton.<\/span><span style=\"color: #DCBDFB\">assignCommand<\/span><span style=\"color: #ADBAC7\">(shuffleCmd)<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">    <\/span><span style=\"color: #768390\">\/\/ test code<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">    addButton.<\/span><span style=\"color: #DCBDFB\">pressed<\/span><span style=\"color: #ADBAC7\">()<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">    addButton.<\/span><span style=\"color: #DCBDFB\">pressed<\/span><span style=\"color: #ADBAC7\">()<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">    addButton.<\/span><span style=\"color: #DCBDFB\">pressed<\/span><span style=\"color: #ADBAC7\">()<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">    addButton.<\/span><span style=\"color: #DCBDFB\">pressed<\/span><span style=\"color: #ADBAC7\">()<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">    addButton.<\/span><span style=\"color: #DCBDFB\">pressed<\/span><span style=\"color: #ADBAC7\">()<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">    <\/span><span style=\"color: #DCBDFB\">println<\/span><span style=\"color: #ADBAC7\">(<\/span><span style=\"color: #96D0FF\">&quot;add test&quot;<\/span><span style=\"color: #ADBAC7\">)<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">    <\/span><span style=\"color: #DCBDFB\">println<\/span><span style=\"color: #ADBAC7\">(musicPlayer.<\/span><span style=\"color: #DCBDFB\">getPlaylist<\/span><span style=\"color: #ADBAC7\">())<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">    shuffleButton.<\/span><span style=\"color: #DCBDFB\">pressed<\/span><span style=\"color: #ADBAC7\">()<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">    <\/span><span style=\"color: #DCBDFB\">println<\/span><span style=\"color: #ADBAC7\">(<\/span><span style=\"color: #96D0FF\">&quot;shuffle test&quot;<\/span><span style=\"color: #ADBAC7\">)<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">    <\/span><span style=\"color: #DCBDFB\">println<\/span><span style=\"color: #ADBAC7\">(musicPlayer.<\/span><span style=\"color: #DCBDFB\">getPlaylist<\/span><span style=\"color: #ADBAC7\">())<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">    musicPlayer.selectedIdx <\/span><span style=\"color: #F47067\">=<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #6CB6FF\">3<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">    deleteButton.<\/span><span style=\"color: #DCBDFB\">pressed<\/span><span style=\"color: #ADBAC7\">()<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">    musicPlayer.selectedIdx <\/span><span style=\"color: #F47067\">=<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #6CB6FF\">0<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">    deleteButton.<\/span><span style=\"color: #DCBDFB\">pressed<\/span><span style=\"color: #ADBAC7\">()<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">    <\/span><span style=\"color: #DCBDFB\">println<\/span><span style=\"color: #ADBAC7\">(<\/span><span style=\"color: #96D0FF\">&quot;delete test&quot;<\/span><span style=\"color: #ADBAC7\">)<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">    <\/span><span style=\"color: #DCBDFB\">println<\/span><span style=\"color: #ADBAC7\">(musicPlayer.<\/span><span style=\"color: #DCBDFB\">getPlaylist<\/span><span style=\"color: #ADBAC7\">())<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">    <\/span><span style=\"color: #DCBDFB\">println<\/span><span style=\"color: #ADBAC7\">(<\/span><span style=\"color: #96D0FF\">&quot;undo test&quot;<\/span><span style=\"color: #ADBAC7\">)<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">    musicPlayer.<\/span><span style=\"color: #DCBDFB\">undo<\/span><span style=\"color: #ADBAC7\">()<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">    <\/span><span style=\"color: #DCBDFB\">println<\/span><span style=\"color: #ADBAC7\">(musicPlayer.<\/span><span style=\"color: #DCBDFB\">getPlaylist<\/span><span style=\"color: #ADBAC7\">())<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">    musicPlayer.<\/span><span style=\"color: #DCBDFB\">undo<\/span><span style=\"color: #ADBAC7\">()<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">    <\/span><span style=\"color: #DCBDFB\">println<\/span><span style=\"color: #ADBAC7\">(musicPlayer.<\/span><span style=\"color: #DCBDFB\">getPlaylist<\/span><span style=\"color: #ADBAC7\">())<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">    musicPlayer.<\/span><span style=\"color: #DCBDFB\">undo<\/span><span style=\"color: #ADBAC7\">()<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">    <\/span><span style=\"color: #DCBDFB\">println<\/span><span style=\"color: #ADBAC7\">(musicPlayer.<\/span><span style=\"color: #DCBDFB\">getPlaylist<\/span><span style=\"color: #ADBAC7\">())<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">    musicPlayer.<\/span><span style=\"color: #DCBDFB\">undo<\/span><span style=\"color: #ADBAC7\">()<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">    <\/span><span style=\"color: #DCBDFB\">println<\/span><span style=\"color: #ADBAC7\">(musicPlayer.<\/span><span style=\"color: #DCBDFB\">getPlaylist<\/span><span style=\"color: #ADBAC7\">())<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">    musicPlayer.<\/span><span style=\"color: #DCBDFB\">undo<\/span><span style=\"color: #ADBAC7\">()<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">    <\/span><span style=\"color: #DCBDFB\">println<\/span><span style=\"color: #ADBAC7\">(musicPlayer.<\/span><span style=\"color: #DCBDFB\">getPlaylist<\/span><span style=\"color: #ADBAC7\">())<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">}<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers\" data-code-block-pro-font-family=\"Code-Pro-Roboto-Mono.ttf\" style=\"font-size:clamp(14px, .875rem, 21px);font-family:Code-Pro-Roboto-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#adbac7;--cbp-line-number-width:calc(2 * 0.6 * .875rem);line-height:clamp(20px, 1.25rem, 30px);--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#22272e\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"54\" height=\"14\" viewBox=\"0 0 54 14\"><g fill=\"none\" fill-rule=\"evenodd\" transform=\"translate(1 1)\"><circle cx=\"6\" cy=\"6\" r=\"6\" fill=\"#FF5F56\" stroke=\"#E0443E\" stroke-width=\".5\"><\/circle><circle cx=\"26\" cy=\"6\" r=\"6\" fill=\"#FFBD2E\" stroke=\"#DEA123\" stroke-width=\".5\"><\/circle><circle cx=\"46\" cy=\"6\" r=\"6\" fill=\"#27C93F\" stroke=\"#1AAB29\" stroke-width=\".5\"><\/circle><\/g><\/svg><\/span><span role=\"button\" tabindex=\"0\" style=\"color:#adbac7;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><pre class=\"code-block-pro-copy-button-pre\" aria-hidden=\"true\"><textarea class=\"code-block-pro-copy-button-textarea\" tabindex=\"-1\" aria-hidden=\"true\" readonly>add test\n&#91;song1, song2, song3, song4, song5&#93;\nshuffle test\n&#91;song5, song4, song2, song1, song3&#93;\ndelete test\n&#91;song4, song2, song3&#93;\nundo test\n&#91;song5, song4, song2, song3&#93;\n&#91;song5, song4, song2, song1, song3&#93;\n&#91;song1, song2, song3, song4, song5&#93;\n&#91;song1, song2, song3, song4&#93;\n&#91;song1, song2, song3&#93;<\/textarea><\/pre><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki github-dark-dimmed\" style=\"background-color: #22272e\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #ADBAC7\">add test<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">&#91;song1, song2, song3, song4, song5&#93;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">shuffle test<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">&#91;song5, song4, song2, song1, song3&#93;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">delete test<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">&#91;song4, song2, song3&#93;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">undo test<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">&#91;song5, song4, song2, song3&#93;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">&#91;song5, song4, song2, song1, song3&#93;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">&#91;song1, song2, song3, song4, song5&#93;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">&#91;song1, song2, song3, song4&#93;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">&#91;song1, song2, song3&#93;<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<p>\uad6c\ud604\ud574\ubcf4\uba74\uc11c \uace0\ubbfc\ub418\ub294 \uc9c0\uc810\uc774 \uba87\uac00\uc9c0 \uc788\uc5c8\ub2e4. <strong>\uccab\ubc88\uc9f8\ub85c \ucee4\ub9e8\ub4dc \uc218\ud589\uc2dc, \uc778\uc790\ub97c \ub118\uaca8\uc57c \ud558\ub294 \uacbd\uc6b0<\/strong>. \ubaa8\ub4e0 \ucee4\ub9e8\ub4dc\uc758 \uc778\uc790\uac00 \ub3d9\uc77c\ud558\ub2e4\uba74, execute()\uc5d0 \uc778\uc790\ub97c \ucd94\uac00\ud558\uba74 \ub418\uaca0\uc9c0\ub9cc, \uadf8\ub807\uc9c0 \uc54a\uc740\uacbd\uc6b0\uac00 \ub9ce\ub2e4. \ubaa8\ub4e0 \ucee4\ub9e8\ub4dc\uac00 \uacf5\ud1b5\uc73c\ub85c \uc0ac\uc6a9\ud560 \ud074\ub798\uc2a4\ub97c \uc0c8\ub85c \ub9cc\ub4e4\uc5b4 \uc778\uc790\ub85c \ub118\uae30\ub294\uac78 \uc0dd\uac01\ud574 \ubcfc \uc218 \uc788\uc744\uac83\uc774\ub2e4. \ucee4\ub9e8\ub4dc\ub9c8\ub2e4 \ud544\uc694\ud55c \ud30c\ub77c\ubbf8\ud130\uac00 \ub2e4\ub974\ub2e4\uba74, \ucee4\ub9e8\ub4dc\ub97c \ub3d9\uc801\uc73c\ub85c \uc0dd\uc131\ud558\uba70, \ud30c\ub77c\ubbf8\ud130\uac12\uc744 \ucee4\ub9e8\ub4dc \uc0dd\uc131\uc790\uc5d0 \ubd80\uc5ec\ud560 \uc218\ub3c4 \uc788\uaca0\ub2e4. \uc5ec\uae30\uc11c\ub294 append\uc2dc\uc5d0 \ucd94\uac00\ud560 \ub178\ub798\uc815\ubcf4\uac00 \ub118\uc5b4\uac00\uc57c \ud558\ub294\ub370, \ubcc4\ub2e4\ub978 \uc778\uc790\uc5c6\uc774 fileopen dialog\ub97c \ub744\uc6cc \uc0ac\uc6a9\uc790 \uc785\ub825\uc744 \ubc1b\ub294\uac78 \uac00\uc815\ud558\uace0 \ub354\ubbf8\ub85c \uad6c\ud604\ud588\ub2e4. <\/p>\n\n\n\n<p><strong>\ub450\ubc88\uc9f8\ub294 \ucee4\ub9e8\ub4dc\uc758 \ub0b4\uc6a9\uc744 Command \ud074\ub798\uc2a4\uac00 \ud560\uc9c0, Receiver\uac00 \ud560\uc9c0\uc774\ub2e4.<\/strong> \uc5ec\uae30\uc11c \uc608\ub97c\ub4e4\uba74, shuffle\uae30\ub2a5 \ubd80\ubd84\uc774 \uc5b4\ub514\uc11c \uad6c\ud604\ud574\uc57c\ud560\uc9c0 \uc560\ub9e4\ud558\ub2e4. \uc5ec\uae30\uc11c\ub294 command \ud074\ub798\uc2a4\uc5d0\uc11c \uad6c\ud604\ud588\ub2e4. \uc774 \ubd80\ubd84\uc740 \ucca8\uc5d0 \ud5f7\uac08\ub838\ub2e4\uac00 \uc870\uae08 \uae4a\uac8c \uc0dd\uac01\ud574\ubcf4\ub2c8 \ub2f5\uc774 \ub098\uc654\ub294\ub370, &#8220;playlist \uc790\uccb4\uac00 shuffle \uae30\ub2a5\uc774 \ud544\uc694\ud55c\uac00?&#8221;\ub97c \uc0dd\uac01\ud558\uba74 \ub41c\ub2e4. playlist\uac00 shuffle\uae30\ub2a5\uc744 \uac16\uac8c\ub418\uba74, \uad6c\ud604\ud55c command\uc758 undo \uae30\ub2a5\uc744 \uc5c9\ub9dd\uc73c\ub85c \ub9cc\ub4e4 \uc218 \uc788\ub2e4. \uadf8\ub798\uc11c command \uc790\uccb4\uc5d0\uc11c shuffle\uc744 \uad6c\ud604\ud588\ub2e4.<\/p>\n\n\n\n<p><strong>\uc138\ubc88\uc9f8\ub294 undo\ub97c \uc704\ud55c command stack \uc744 \uc5b4\ub5bb\uac8c \uad6c\ud604\ud560\uc9c0 \ubd80\ubd84\uc774\ub2e4.<\/strong> \ubc84\ud2bc\uc774 \ub20c\ub9b4 \ub54c, command\ub97c \uc0c8\ub85c \uc0dd\uc131\ud558\uace0 \uc788\uc9c0 \uc54a\uc73c\ubbc0\ub85c, \uadf8\ub300\ub85c stack\uc5d0 \uc313\uc73c\uba74, \ub370\uc774\ud130\uac00 \uacb9\uccd0 \uc368\uc838\uc11c \uc81c\ub300\ub85c \uc791\ub3d9\ud558\uc9c0 \uc54a\ub294\ub2e4. \uc5ec\uae30\uc11c\ub294 stack \ubd80\ubd84\uc774 \ub9c8\uc9c0\ub9c9\uc5d0 \uad6c\ud604\ub418\uc5b4\uc11c command\uac00 \uc790\uae30\uc790\uc2e0\uc744 \ubcf5\uc0ac\ud558\uc5ec stack\uc5d0 \uc313\ub3c4\ub85d \uad6c\ud604\ud588\ub2e4. \uc608\uc81c\uc5d0\uc11c\ub294 \uac01\uac01 \uad6c\ud604\uc774 \ub418\uc5c8\uc9c0\ub9cc, \uc7a5\uae30\uc801\uc73c\ub85c undo\ub97c \uc0dd\uac01\ud55c\ub2e4\uba74, command \ud074\ub798\uc2a4\uc5d0 clone \ud568\uc218 \uad6c\ud604\uc744 \uace0\ub824\ud574\ubd10\uc57c\uaca0\ub2e4. \ub610\ub294, \ubc84\ud2bc\uc5d0\uc11c command \uc778\uc2a4\ud134\uc2a4\ub97c factory method \ubc29\ubc95\uc744 \uc774\uc6a9\ud558\uc5ec \uc0dd\uc131\ud558\ub294 \uac83\ub3c4 \ud55c\uac00\uc9c0 \uc120\ud0dd\uc9c0\uac00 \ub420 \uac83\uc774\ub2e4.<br> \ub610 \ud558\ub098, \uccab \uad6c\ud604\uc5d0\uc11c DummyMusicPlayer\uc548\uc5d0 undo \uae30\ub2a5\uc744 \uad6c\ud604\ud588\uc5c8\ub2e4. Python \uad6c\ud604\uc2dc, circular import \ubb38\uc81c\uac00 \uc0dd\uae30\uace0 \ub098\uc11c\uc57c \uc798\ubabb\ub41c\uac78 \uc54c\uc558\ub294\ub370, Receiver \uac1d\uccb4\ub294 Command\uc5d0 \ub300\ud574 \uc54c \ud544\uc694\uac00 \uc5c6\ub2e4. \uadf8\ub798\uc11c undo stack\uc744 \ube7c\ub0b4\uc5b4 \uc678\ubd80\uc5d0 \ub9cc\ub4e4\uace0, client \ucf54\ub4dc\uc5d0\uc11c \uad00\ub9ac\ud558\ub3c4\ub85d \ub9cc\ub4e4\uc5c8\ub2e4. <\/p>\n\n\n\n<hr class=\"wp-block-separator has-css-opacity is-style-dots\"\/>\n\n\n\n<h3 class=\"wp-block-heading\">C#<\/h3>\n\n\n\n<p>C#\uc740 \uc720\ub2c8\ud2f0\uc5d0\uc11c \ud14c\uc2a4\ud2b8 \ud588\ub2e4. cmdmain.cs\ub9cc empty obejct\ub97c \uc0dd\uc131\ud574\uc11c \ucef4\ud3ec\ub10c\ud2b8\ub85c \ucd94\uac00\ud558\uc5ec \uc2e4\ud589\ub418\ub3c4\ub85d \ud588\ub2e4. <\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers\" data-code-block-pro-font-family=\"Code-Pro-Roboto-Mono.ttf\" style=\"font-size:clamp(14px, .875rem, 21px);font-family:Code-Pro-Roboto-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#adbac7;--cbp-line-number-width:calc(2 * 0.6 * .875rem);line-height:clamp(20px, 1.25rem, 30px);--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#22272e\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"54\" height=\"14\" viewBox=\"0 0 54 14\"><g fill=\"none\" fill-rule=\"evenodd\" transform=\"translate(1 1)\"><circle cx=\"6\" cy=\"6\" r=\"6\" fill=\"#FF5F56\" stroke=\"#E0443E\" stroke-width=\".5\"><\/circle><circle cx=\"26\" cy=\"6\" r=\"6\" fill=\"#FFBD2E\" stroke=\"#DEA123\" stroke-width=\".5\"><\/circle><circle cx=\"46\" cy=\"6\" r=\"6\" fill=\"#27C93F\" stroke=\"#1AAB29\" stroke-width=\".5\"><\/circle><\/g><\/svg><\/span><span role=\"button\" tabindex=\"0\" style=\"color:#adbac7;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><pre class=\"code-block-pro-copy-button-pre\" aria-hidden=\"true\"><textarea class=\"code-block-pro-copy-button-textarea\" tabindex=\"-1\" aria-hidden=\"true\" readonly>using System;\nusing System.Collections.Generic;\nusing System.Linq;\n\nnamespace command\n{\n    class DummyMusicPlayer\n    {\n        private List&lt;String> playlist = new List&lt;String>();\n\n        public int Selected\n        {\n            get; set;\n        }\n\n        public DummyMusicPlayer()\n        {\n            Selected = 0;\n        }\n\n        public List&lt;String> Playlist\n        {\n            get\n            {\n                return playlist;\n            }\n            set\n            {\n                playlist.Clear();\n                playlist = value;\n            }\n        }\n\n        public void clearPlaylist()\n        {\n            playlist.Clear();\n        }\n\n        public int append(String song)\n        {\n            playlist.Add(song);\n            return playlist.Count() - 1;\n        }\n\n        public void insert(int idx, String song)\n        {\n            playlist.Insert(idx, song);\n        }\n\n        public String delete(int idx = -1)\n        {\n            String song = null;\n            if (idx == -1)\n            {\n                song = playlist&#91;Selected&#93;;\n                playlist.RemoveAt(Selected);\n            }\n            else\n            {\n                song = playlist&#91;idx&#93;;\n                playlist.RemoveAt(idx);\n            }\n\n            return song;\n        }\n    }\n}\n<\/textarea><\/pre><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki github-dark-dimmed\" style=\"background-color: #22272e\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #F47067\">using<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #F69D50\">System<\/span><span style=\"color: #ADBAC7\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F47067\">using<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #F69D50\">System<\/span><span style=\"color: #ADBAC7\">.<\/span><span style=\"color: #F69D50\">Collections<\/span><span style=\"color: #ADBAC7\">.<\/span><span style=\"color: #F69D50\">Generic<\/span><span style=\"color: #ADBAC7\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F47067\">using<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #F69D50\">System<\/span><span style=\"color: #ADBAC7\">.<\/span><span style=\"color: #F69D50\">Linq<\/span><span style=\"color: #ADBAC7\">;<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #F47067\">namespace<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #F69D50\">command<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">{<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">    <\/span><span style=\"color: #F47067\">class<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #F69D50\">DummyMusicPlayer<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">    {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">        <\/span><span style=\"color: #F47067\">private<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #F69D50\">List<\/span><span style=\"color: #ADBAC7\">&lt;<\/span><span style=\"color: #F69D50\">String<\/span><span style=\"color: #ADBAC7\">&gt; <\/span><span style=\"color: #F69D50\">playlist<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #F47067\">=<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #F47067\">new<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #F69D50\">List<\/span><span style=\"color: #ADBAC7\">&lt;<\/span><span style=\"color: #F69D50\">String<\/span><span style=\"color: #ADBAC7\">&gt;();<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">        <\/span><span style=\"color: #F47067\">public<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #F47067\">int<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #F69D50\">Selected<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">        {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">            <\/span><span style=\"color: #F47067\">get<\/span><span style=\"color: #ADBAC7\">; <\/span><span style=\"color: #F47067\">set<\/span><span style=\"color: #ADBAC7\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">        }<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">        <\/span><span style=\"color: #F47067\">public<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #DCBDFB\">DummyMusicPlayer<\/span><span style=\"color: #ADBAC7\">()<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">        {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">            Selected <\/span><span style=\"color: #F47067\">=<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #6CB6FF\">0<\/span><span style=\"color: #ADBAC7\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">        }<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">        <\/span><span style=\"color: #F47067\">public<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #F69D50\">List<\/span><span style=\"color: #ADBAC7\">&lt;<\/span><span style=\"color: #F69D50\">String<\/span><span style=\"color: #ADBAC7\">&gt; <\/span><span style=\"color: #F69D50\">Playlist<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">        {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">            <\/span><span style=\"color: #F47067\">get<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">            {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">                <\/span><span style=\"color: #F47067\">return<\/span><span style=\"color: #ADBAC7\"> playlist;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">            }<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">            <\/span><span style=\"color: #F47067\">set<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">            {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">                playlist.<\/span><span style=\"color: #DCBDFB\">Clear<\/span><span style=\"color: #ADBAC7\">();<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">                playlist <\/span><span style=\"color: #F47067\">=<\/span><span style=\"color: #ADBAC7\"> value;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">            }<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">        }<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">        <\/span><span style=\"color: #F47067\">public<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #F47067\">void<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #DCBDFB\">clearPlaylist<\/span><span style=\"color: #ADBAC7\">()<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">        {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">            playlist.<\/span><span style=\"color: #DCBDFB\">Clear<\/span><span style=\"color: #ADBAC7\">();<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">        }<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">        <\/span><span style=\"color: #F47067\">public<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #F47067\">int<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #DCBDFB\">append<\/span><span style=\"color: #ADBAC7\">(<\/span><span style=\"color: #F69D50\">String<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #F69D50\">song<\/span><span style=\"color: #ADBAC7\">)<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">        {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">            playlist.<\/span><span style=\"color: #DCBDFB\">Add<\/span><span style=\"color: #ADBAC7\">(song);<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">            <\/span><span style=\"color: #F47067\">return<\/span><span style=\"color: #ADBAC7\"> playlist.<\/span><span style=\"color: #DCBDFB\">Count<\/span><span style=\"color: #ADBAC7\">() <\/span><span style=\"color: #F47067\">-<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #6CB6FF\">1<\/span><span style=\"color: #ADBAC7\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">        }<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">        <\/span><span style=\"color: #F47067\">public<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #F47067\">void<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #DCBDFB\">insert<\/span><span style=\"color: #ADBAC7\">(<\/span><span style=\"color: #F47067\">int<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #F69D50\">idx<\/span><span style=\"color: #ADBAC7\">, <\/span><span style=\"color: #F69D50\">String<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #F69D50\">song<\/span><span style=\"color: #ADBAC7\">)<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">        {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">            playlist.<\/span><span style=\"color: #DCBDFB\">Insert<\/span><span style=\"color: #ADBAC7\">(idx, song);<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">        }<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">        <\/span><span style=\"color: #F47067\">public<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #F69D50\">String<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #DCBDFB\">delete<\/span><span style=\"color: #ADBAC7\">(<\/span><span style=\"color: #F47067\">int<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #F69D50\">idx<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #F47067\">=<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #F47067\">-<\/span><span style=\"color: #6CB6FF\">1<\/span><span style=\"color: #ADBAC7\">)<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">        {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">            <\/span><span style=\"color: #F69D50\">String<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #F69D50\">song<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #F47067\">=<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #6CB6FF\">null<\/span><span style=\"color: #ADBAC7\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">            <\/span><span style=\"color: #F47067\">if<\/span><span style=\"color: #ADBAC7\"> (idx <\/span><span style=\"color: #F47067\">==<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #F47067\">-<\/span><span style=\"color: #6CB6FF\">1<\/span><span style=\"color: #ADBAC7\">)<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">            {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">                song <\/span><span style=\"color: #F47067\">=<\/span><span style=\"color: #ADBAC7\"> playlist&#91;Selected&#93;;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">                playlist.<\/span><span style=\"color: #DCBDFB\">RemoveAt<\/span><span style=\"color: #ADBAC7\">(Selected);<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">            }<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">            <\/span><span style=\"color: #F47067\">else<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">            {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">                song <\/span><span style=\"color: #F47067\">=<\/span><span style=\"color: #ADBAC7\"> playlist&#91;idx&#93;;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">                playlist.<\/span><span style=\"color: #DCBDFB\">RemoveAt<\/span><span style=\"color: #ADBAC7\">(idx);<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">            }<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">            <\/span><span style=\"color: #F47067\">return<\/span><span style=\"color: #ADBAC7\"> song;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">        }<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">    }<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">}<\/span><\/span>\n<span class=\"line\"><\/span><\/code><\/pre><\/div>\n\n\n\n<p>\uc55e\uc5d0\uc11c \ubd24\ub4ef\uc774 command\uc640 \ub3c5\ub9bd\uc801\uc778 Receiver\ub85c DummyMusicPlayer\ub97c \ub9cc\ub4e4\uc5c8\ub2e4. Playlist\uc640 Selected\ub97c property\ub85c \uad6c\ud604\ud588\ub2e4.<\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers\" data-code-block-pro-font-family=\"Code-Pro-Roboto-Mono.ttf\" style=\"font-size:clamp(14px, .875rem, 21px);font-family:Code-Pro-Roboto-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#adbac7;--cbp-line-number-width:calc(2 * 0.6 * .875rem);line-height:clamp(20px, 1.25rem, 30px);--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#22272e\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"54\" height=\"14\" viewBox=\"0 0 54 14\"><g fill=\"none\" fill-rule=\"evenodd\" transform=\"translate(1 1)\"><circle cx=\"6\" cy=\"6\" r=\"6\" fill=\"#FF5F56\" stroke=\"#E0443E\" stroke-width=\".5\"><\/circle><circle cx=\"26\" cy=\"6\" r=\"6\" fill=\"#FFBD2E\" stroke=\"#DEA123\" stroke-width=\".5\"><\/circle><circle cx=\"46\" cy=\"6\" r=\"6\" fill=\"#27C93F\" stroke=\"#1AAB29\" stroke-width=\".5\"><\/circle><\/g><\/svg><\/span><span role=\"button\" tabindex=\"0\" style=\"color:#adbac7;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><pre class=\"code-block-pro-copy-button-pre\" aria-hidden=\"true\"><textarea class=\"code-block-pro-copy-button-textarea\" tabindex=\"-1\" aria-hidden=\"true\" readonly>\nnamespace command\n{\n    interface ICommand\n    {\n        void execute();\n        void undo();\n    }\n}\n<\/textarea><\/pre><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki github-dark-dimmed\" style=\"background-color: #22272e\" tabindex=\"0\"><code><span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #F47067\">namespace<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #F69D50\">command<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">{<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">    <\/span><span style=\"color: #F47067\">interface<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #F69D50\">ICommand<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">    {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">        <\/span><span style=\"color: #F47067\">void<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #DCBDFB\">execute<\/span><span style=\"color: #ADBAC7\">();<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">        <\/span><span style=\"color: #F47067\">void<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #DCBDFB\">undo<\/span><span style=\"color: #ADBAC7\">();<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">    }<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">}<\/span><\/span>\n<span class=\"line\"><\/span><\/code><\/pre><\/div>\n\n\n\n<p>Command \uc778\ud130\ud398\uc774\uc2a4. execute, undo \uac00 \uc778\ud130\ud398\uc774\uc2a4\ub85c \ub178\ucd9c\ub41c\ub2e4.<\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers\" data-code-block-pro-font-family=\"Code-Pro-Roboto-Mono.ttf\" style=\"font-size:clamp(14px, .875rem, 21px);font-family:Code-Pro-Roboto-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#adbac7;--cbp-line-number-width:calc(2 * 0.6 * .875rem);line-height:clamp(20px, 1.25rem, 30px);--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#22272e\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"54\" height=\"14\" viewBox=\"0 0 54 14\"><g fill=\"none\" fill-rule=\"evenodd\" transform=\"translate(1 1)\"><circle cx=\"6\" cy=\"6\" r=\"6\" fill=\"#FF5F56\" stroke=\"#E0443E\" stroke-width=\".5\"><\/circle><circle cx=\"26\" cy=\"6\" r=\"6\" fill=\"#FFBD2E\" stroke=\"#DEA123\" stroke-width=\".5\"><\/circle><circle cx=\"46\" cy=\"6\" r=\"6\" fill=\"#27C93F\" stroke=\"#1AAB29\" stroke-width=\".5\"><\/circle><\/g><\/svg><\/span><span role=\"button\" tabindex=\"0\" style=\"color:#adbac7;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><pre class=\"code-block-pro-copy-button-pre\" aria-hidden=\"true\"><textarea class=\"code-block-pro-copy-button-textarea\" tabindex=\"-1\" aria-hidden=\"true\" readonly>using System.Collections.Generic;\n\nnamespace command\n{\n    class CommandStack\n    {\n        private Stack&lt;ICommand> commandStack = new Stack&lt;ICommand>();\n\n        public void pushCmd(ICommand cmd)\n        {\n            commandStack.Push(cmd);\n        }\n\n        private ICommand popCmd()\n        {\n            ICommand cmd = null;\n            if(commandStack.Count > 0)\n            {\n                cmd = commandStack.Pop();\n            }\n\n            return cmd;\n        }\n\n        public void undo()\n        {\n            popCmd()?.undo();\n        }\n    }\n}\n<\/textarea><\/pre><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki github-dark-dimmed\" style=\"background-color: #22272e\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #F47067\">using<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #F69D50\">System<\/span><span style=\"color: #ADBAC7\">.<\/span><span style=\"color: #F69D50\">Collections<\/span><span style=\"color: #ADBAC7\">.<\/span><span style=\"color: #F69D50\">Generic<\/span><span style=\"color: #ADBAC7\">;<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #F47067\">namespace<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #F69D50\">command<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">{<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">    <\/span><span style=\"color: #F47067\">class<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #F69D50\">CommandStack<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">    {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">        <\/span><span style=\"color: #F47067\">private<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #F69D50\">Stack<\/span><span style=\"color: #ADBAC7\">&lt;<\/span><span style=\"color: #F69D50\">ICommand<\/span><span style=\"color: #ADBAC7\">&gt; <\/span><span style=\"color: #F69D50\">commandStack<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #F47067\">=<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #F47067\">new<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #F69D50\">Stack<\/span><span style=\"color: #ADBAC7\">&lt;<\/span><span style=\"color: #F69D50\">ICommand<\/span><span style=\"color: #ADBAC7\">&gt;();<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">        <\/span><span style=\"color: #F47067\">public<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #F47067\">void<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #DCBDFB\">pushCmd<\/span><span style=\"color: #ADBAC7\">(<\/span><span style=\"color: #F69D50\">ICommand<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #F69D50\">cmd<\/span><span style=\"color: #ADBAC7\">)<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">        {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">            commandStack.<\/span><span style=\"color: #DCBDFB\">Push<\/span><span style=\"color: #ADBAC7\">(cmd);<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">        }<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">        <\/span><span style=\"color: #F47067\">private<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #F69D50\">ICommand<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #DCBDFB\">popCmd<\/span><span style=\"color: #ADBAC7\">()<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">        {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">            <\/span><span style=\"color: #F69D50\">ICommand<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #F69D50\">cmd<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #F47067\">=<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #6CB6FF\">null<\/span><span style=\"color: #ADBAC7\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">            <\/span><span style=\"color: #F47067\">if<\/span><span style=\"color: #ADBAC7\">(commandStack.Count <\/span><span style=\"color: #F47067\">&gt;<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #6CB6FF\">0<\/span><span style=\"color: #ADBAC7\">)<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">            {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">                cmd <\/span><span style=\"color: #F47067\">=<\/span><span style=\"color: #ADBAC7\"> commandStack.<\/span><span style=\"color: #DCBDFB\">Pop<\/span><span style=\"color: #ADBAC7\">();<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">            }<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">            <\/span><span style=\"color: #F47067\">return<\/span><span style=\"color: #ADBAC7\"> cmd;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">        }<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">        <\/span><span style=\"color: #F47067\">public<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #F47067\">void<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #DCBDFB\">undo<\/span><span style=\"color: #ADBAC7\">()<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">        {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">            <\/span><span style=\"color: #DCBDFB\">popCmd<\/span><span style=\"color: #ADBAC7\">()<\/span><span style=\"color: #F47067\">?<\/span><span style=\"color: #ADBAC7\">.<\/span><span style=\"color: #DCBDFB\">undo<\/span><span style=\"color: #ADBAC7\">();<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">        }<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">    }<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">}<\/span><\/span>\n<span class=\"line\"><\/span><\/code><\/pre><\/div>\n\n\n\n<p>undo\ub97c \uc704\ud574 command\ub97c \uc800\uc7a5\ud560 \uc2a4\ud0dd. \uc2a4\ud0dd\uc740 Kotlin\uc5d0\uc120 \uc5c6\uc5b4\uc11c \uc9c1\uc811 \uad6c\ud604\ud588\uace0, C#\uc740 \uc9c0\uc6d0\ud558\ub294 \uc790\ub8cc\uad6c\uc870\ub77c\uc11c \ubcc4\ub3c4 \uad6c\ud604\uc774 \ud544\uc694\uc5c6\ub2e4. \ub098\uc911\uc5d0 \ubcf4\uaca0\uc9c0\ub9cc, Python\uc740 List\uac00 stack\uc5d0 \ud574\ub2f9\ud558\ub294 \uae30\ub2a5\ub3c4 \ud558\uae30 \ub54c\ubb38\uc5d0 \uc774\ub97c \uc774\uc6a9\ud55c\ub2e4. \uc5b8\uc5b4\ubcc4 \uad6c\ud604 \ucc28\uc774\uc810\uc774 \ud765\ubbf8\ub85c\uc6c0. \uadf8\ub0e5 \ub3d9\uc77c\ud558\uac8c \ub2e4 \uc9c0\uc6d0\ud574\uc8fc\uba74 \uc88b\uc744\uac70 \uac19\uc740\ub370.<\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers\" data-code-block-pro-font-family=\"Code-Pro-Roboto-Mono.ttf\" style=\"font-size:clamp(14px, .875rem, 21px);font-family:Code-Pro-Roboto-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#adbac7;--cbp-line-number-width:calc(2 * 0.6 * .875rem);line-height:clamp(20px, 1.25rem, 30px);--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#22272e\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"54\" height=\"14\" viewBox=\"0 0 54 14\"><g fill=\"none\" fill-rule=\"evenodd\" transform=\"translate(1 1)\"><circle cx=\"6\" cy=\"6\" r=\"6\" fill=\"#FF5F56\" stroke=\"#E0443E\" stroke-width=\".5\"><\/circle><circle cx=\"26\" cy=\"6\" r=\"6\" fill=\"#FFBD2E\" stroke=\"#DEA123\" stroke-width=\".5\"><\/circle><circle cx=\"46\" cy=\"6\" r=\"6\" fill=\"#27C93F\" stroke=\"#1AAB29\" stroke-width=\".5\"><\/circle><\/g><\/svg><\/span><span role=\"button\" tabindex=\"0\" style=\"color:#adbac7;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><pre class=\"code-block-pro-copy-button-pre\" aria-hidden=\"true\"><textarea class=\"code-block-pro-copy-button-textarea\" tabindex=\"-1\" aria-hidden=\"true\" readonly>\nnamespace command\n{\n    class DummyButton\n    {\n        private string name = null;\n        private ICommand command = null;\n\n        public DummyButton(string buttonName)\n        {\n            name = buttonName;\n        }\n\n        public void assignCommand(ICommand cmd)\n        {\n            command = cmd;\n        }\n\n        public void pressed()\n        {\n            command?.execute();\n        }\n    }\n}\n<\/textarea><\/pre><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki github-dark-dimmed\" style=\"background-color: #22272e\" tabindex=\"0\"><code><span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #F47067\">namespace<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #F69D50\">command<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">{<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">    <\/span><span style=\"color: #F47067\">class<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #F69D50\">DummyButton<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">    {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">        <\/span><span style=\"color: #F47067\">private<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #F47067\">string<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #F69D50\">name<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #F47067\">=<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #6CB6FF\">null<\/span><span style=\"color: #ADBAC7\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">        <\/span><span style=\"color: #F47067\">private<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #F69D50\">ICommand<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #F69D50\">command<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #F47067\">=<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #6CB6FF\">null<\/span><span style=\"color: #ADBAC7\">;<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">        <\/span><span style=\"color: #F47067\">public<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #DCBDFB\">DummyButton<\/span><span style=\"color: #ADBAC7\">(<\/span><span style=\"color: #F47067\">string<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #F69D50\">buttonName<\/span><span style=\"color: #ADBAC7\">)<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">        {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">            name <\/span><span style=\"color: #F47067\">=<\/span><span style=\"color: #ADBAC7\"> buttonName;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">        }<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">        <\/span><span style=\"color: #F47067\">public<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #F47067\">void<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #DCBDFB\">assignCommand<\/span><span style=\"color: #ADBAC7\">(<\/span><span style=\"color: #F69D50\">ICommand<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #F69D50\">cmd<\/span><span style=\"color: #ADBAC7\">)<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">        {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">            command <\/span><span style=\"color: #F47067\">=<\/span><span style=\"color: #ADBAC7\"> cmd;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">        }<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">        <\/span><span style=\"color: #F47067\">public<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #F47067\">void<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #DCBDFB\">pressed<\/span><span style=\"color: #ADBAC7\">()<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">        {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">            command<\/span><span style=\"color: #F47067\">?<\/span><span style=\"color: #ADBAC7\">.<\/span><span style=\"color: #DCBDFB\">execute<\/span><span style=\"color: #ADBAC7\">();<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">        }<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">    }<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">}<\/span><\/span>\n<span class=\"line\"><\/span><\/code><\/pre><\/div>\n\n\n\n<p>Invoker \uc5ed\ud560\uc758 DummyButton\uc774\ub2e4. Unity\ub77c\uace0 \ud2b9\ubcc4\ud788 \ubcc4\ub3c4 \uad6c\ud604\ud558\uc9c0 \uc54a\uace0 \uadf8\ub300\ub85c \uc0ac\uc6a9\ud588\ub2e4. Kotlin\uacfc \ub2ec\ub9ac C#\uc5d0\uc11c\ub294 Access modifier\ub97c public\uc73c\ub85c \uc9c0\uc815\ud574\uc918\uc57c \uc678\ubd80\uc5d0\uc11c \uc0ac\uc6a9\uac00\ub2a5\ud558\ub2e4. <\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers\" data-code-block-pro-font-family=\"Code-Pro-Roboto-Mono.ttf\" style=\"font-size:clamp(14px, .875rem, 21px);font-family:Code-Pro-Roboto-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#adbac7;--cbp-line-number-width:calc(3 * 0.6 * .875rem);line-height:clamp(20px, 1.25rem, 30px);--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#22272e\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"54\" height=\"14\" viewBox=\"0 0 54 14\"><g fill=\"none\" fill-rule=\"evenodd\" transform=\"translate(1 1)\"><circle cx=\"6\" cy=\"6\" r=\"6\" fill=\"#FF5F56\" stroke=\"#E0443E\" stroke-width=\".5\"><\/circle><circle cx=\"26\" cy=\"6\" r=\"6\" fill=\"#FFBD2E\" stroke=\"#DEA123\" stroke-width=\".5\"><\/circle><circle cx=\"46\" cy=\"6\" r=\"6\" fill=\"#27C93F\" stroke=\"#1AAB29\" stroke-width=\".5\"><\/circle><\/g><\/svg><\/span><span role=\"button\" tabindex=\"0\" style=\"color:#adbac7;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><pre class=\"code-block-pro-copy-button-pre\" aria-hidden=\"true\"><textarea class=\"code-block-pro-copy-button-textarea\" tabindex=\"-1\" aria-hidden=\"true\" readonly>using System;\nusing System.Collections.Generic;\nusing System.Linq;\n\n\nnamespace command\n{\n    class ShuffleCommand : ICommand\n    {\n        private DummyMusicPlayer receiver = null;\n        private CommandStack undoStack = null;\n        private List&lt;String> playlistBackup = null;\n\n        public ShuffleCommand(DummyMusicPlayer receiver, CommandStack undoStack)\n        {\n            this.receiver = receiver;\n            this.undoStack = undoStack;\n        }\n        public void execute()\n        {\n            List&lt;String> playlist = receiver.Playlist;\n            playlistBackup = playlist.ConvertAll(s => s);            \n            playlist.shuffle();\n            \n            ShuffleCommand cmd = new ShuffleCommand(receiver, undoStack);\n            cmd.playlistBackup = playlistBackup.ConvertAll(s => s);\n            undoStack.pushCmd(cmd);\n        }\n\n        public void undo()\n        {\n            if(playlistBackup != null)\n            {\n                receiver.clearPlaylist();\n                receiver.Playlist = playlistBackup;\n            }\n        }\n    }\n\n    class AppendCommand: ICommand\n    {\n        private DummyMusicPlayer receiver = null;\n        private CommandStack undoStack = null;\n        private int idx = -1;\n\n        public AppendCommand(DummyMusicPlayer receiver, CommandStack undoStack)\n        {\n            this.receiver = receiver;\n            this.undoStack = undoStack;\n        }\n\n        public void execute()\n        {\n            String song = DummyFileOpenDialog.callFileOpenDlg();\n            idx = receiver.append(song);\n\n            AppendCommand cmd = new AppendCommand(receiver, undoStack);\n            cmd.idx = idx;\n            undoStack.pushCmd(cmd);\n        }\n\n        public void undo()\n        {\n            if(idx != -1)\n            {\n                receiver.delete(idx);\n            }\n        }\n    }\n\n    class DeleteCommand : ICommand\n    {\n        private DummyMusicPlayer receiver = null;\n        private CommandStack undoStack = null;\n        private String song = \"\";\n        private int idx = -1;\n\n        public DeleteCommand(DummyMusicPlayer receiver, CommandStack undoStack)\n        {\n            this.receiver = receiver;\n            this.undoStack = undoStack;\n        }\n\n        public void execute()\n        {\n            idx = receiver.Selected;\n            song = receiver.delete();\n\n            DeleteCommand cmd = new DeleteCommand(receiver, undoStack);\n            cmd.song = song;\n            cmd.idx = idx;\n            undoStack.pushCmd(cmd);\n        }\n\n        public void undo()\n        {\n            if(idx != -1)\n            {\n                receiver.insert(idx, song);\n            }\n        }\n    }\n\n    static class DummyFileOpenDialog\n    {\n        private static List&lt;String> testSongs = new List&lt;String> { \"song1\", \"song2\", \"song3\", \"song4\", \"song5\" };\n        private static int fileOpenIdx = 0;\n\n        public static String callFileOpenDlg()\n        {\n            String song = testSongs&#91;fileOpenIdx&#93;;\n            fileOpenIdx++;\n            if (fileOpenIdx >= testSongs.Count()) fileOpenIdx = 0;\n\n            return song;\n        }\n    }\n\n    static class Shuffle\n    {\n        private static Random rng = new Random();\n        public static void shuffle&lt;T>(this IList&lt;T> list)\n        {\n            int n = list.Count;\n            while (n > 1)\n            {\n                n--;\n                int k = rng.Next(n + 1);\n                T value = list&#91;k&#93;;\n                list&#91;k&#93; = list&#91;n&#93;;\n                list&#91;n&#93; = value;\n            }\n        }\n    }\n\n}\n<\/textarea><\/pre><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki github-dark-dimmed\" style=\"background-color: #22272e\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #F47067\">using<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #F69D50\">System<\/span><span style=\"color: #ADBAC7\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F47067\">using<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #F69D50\">System<\/span><span style=\"color: #ADBAC7\">.<\/span><span style=\"color: #F69D50\">Collections<\/span><span style=\"color: #ADBAC7\">.<\/span><span style=\"color: #F69D50\">Generic<\/span><span style=\"color: #ADBAC7\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F47067\">using<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #F69D50\">System<\/span><span style=\"color: #ADBAC7\">.<\/span><span style=\"color: #F69D50\">Linq<\/span><span style=\"color: #ADBAC7\">;<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #F47067\">namespace<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #F69D50\">command<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">{<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">    <\/span><span style=\"color: #F47067\">class<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #F69D50\">ShuffleCommand<\/span><span style=\"color: #ADBAC7\"> : <\/span><span style=\"color: #F69D50\">ICommand<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">    {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">        <\/span><span style=\"color: #F47067\">private<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #F69D50\">DummyMusicPlayer<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #F69D50\">receiver<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #F47067\">=<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #6CB6FF\">null<\/span><span style=\"color: #ADBAC7\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">        <\/span><span style=\"color: #F47067\">private<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #F69D50\">CommandStack<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #F69D50\">undoStack<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #F47067\">=<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #6CB6FF\">null<\/span><span style=\"color: #ADBAC7\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">        <\/span><span style=\"color: #F47067\">private<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #F69D50\">List<\/span><span style=\"color: #ADBAC7\">&lt;<\/span><span style=\"color: #F69D50\">String<\/span><span style=\"color: #ADBAC7\">&gt; <\/span><span style=\"color: #F69D50\">playlistBackup<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #F47067\">=<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #6CB6FF\">null<\/span><span style=\"color: #ADBAC7\">;<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">        <\/span><span style=\"color: #F47067\">public<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #DCBDFB\">ShuffleCommand<\/span><span style=\"color: #ADBAC7\">(<\/span><span style=\"color: #F69D50\">DummyMusicPlayer<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #F69D50\">receiver<\/span><span style=\"color: #ADBAC7\">, <\/span><span style=\"color: #F69D50\">CommandStack<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #F69D50\">undoStack<\/span><span style=\"color: #ADBAC7\">)<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">        {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">            <\/span><span style=\"color: #6CB6FF\">this<\/span><span style=\"color: #ADBAC7\">.receiver <\/span><span style=\"color: #F47067\">=<\/span><span style=\"color: #ADBAC7\"> receiver;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">            <\/span><span style=\"color: #6CB6FF\">this<\/span><span style=\"color: #ADBAC7\">.undoStack <\/span><span style=\"color: #F47067\">=<\/span><span style=\"color: #ADBAC7\"> undoStack;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">        }<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">        <\/span><span style=\"color: #F47067\">public<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #F47067\">void<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #DCBDFB\">execute<\/span><span style=\"color: #ADBAC7\">()<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">        {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">            <\/span><span style=\"color: #F69D50\">List<\/span><span style=\"color: #ADBAC7\">&lt;<\/span><span style=\"color: #F69D50\">String<\/span><span style=\"color: #ADBAC7\">&gt; <\/span><span style=\"color: #F69D50\">playlist<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #F47067\">=<\/span><span style=\"color: #ADBAC7\"> receiver.Playlist;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">            playlistBackup <\/span><span style=\"color: #F47067\">=<\/span><span style=\"color: #ADBAC7\"> playlist.<\/span><span style=\"color: #DCBDFB\">ConvertAll<\/span><span style=\"color: #ADBAC7\">(<\/span><span style=\"color: #F69D50\">s<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #F47067\">=&gt;<\/span><span style=\"color: #ADBAC7\"> s);            <\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">            playlist.<\/span><span style=\"color: #DCBDFB\">shuffle<\/span><span style=\"color: #ADBAC7\">();<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">            <\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">            <\/span><span style=\"color: #F69D50\">ShuffleCommand<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #F69D50\">cmd<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #F47067\">=<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #F47067\">new<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #F69D50\">ShuffleCommand<\/span><span style=\"color: #ADBAC7\">(receiver, undoStack);<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">            cmd.playlistBackup <\/span><span style=\"color: #F47067\">=<\/span><span style=\"color: #ADBAC7\"> playlistBackup.<\/span><span style=\"color: #DCBDFB\">ConvertAll<\/span><span style=\"color: #ADBAC7\">(<\/span><span style=\"color: #F69D50\">s<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #F47067\">=&gt;<\/span><span style=\"color: #ADBAC7\"> s);<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">            undoStack.<\/span><span style=\"color: #DCBDFB\">pushCmd<\/span><span style=\"color: #ADBAC7\">(cmd);<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">        }<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">        <\/span><span style=\"color: #F47067\">public<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #F47067\">void<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #DCBDFB\">undo<\/span><span style=\"color: #ADBAC7\">()<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">        {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">            <\/span><span style=\"color: #F47067\">if<\/span><span style=\"color: #ADBAC7\">(playlistBackup <\/span><span style=\"color: #F47067\">!=<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #6CB6FF\">null<\/span><span style=\"color: #ADBAC7\">)<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">            {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">                receiver.<\/span><span style=\"color: #DCBDFB\">clearPlaylist<\/span><span style=\"color: #ADBAC7\">();<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">                receiver.Playlist <\/span><span style=\"color: #F47067\">=<\/span><span style=\"color: #ADBAC7\"> playlistBackup;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">            }<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">        }<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">    }<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">    <\/span><span style=\"color: #F47067\">class<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #F69D50\">AppendCommand<\/span><span style=\"color: #ADBAC7\">: <\/span><span style=\"color: #F69D50\">ICommand<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">    {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">        <\/span><span style=\"color: #F47067\">private<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #F69D50\">DummyMusicPlayer<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #F69D50\">receiver<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #F47067\">=<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #6CB6FF\">null<\/span><span style=\"color: #ADBAC7\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">        <\/span><span style=\"color: #F47067\">private<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #F69D50\">CommandStack<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #F69D50\">undoStack<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #F47067\">=<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #6CB6FF\">null<\/span><span style=\"color: #ADBAC7\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">        <\/span><span style=\"color: #F47067\">private<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #F47067\">int<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #F69D50\">idx<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #F47067\">=<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #F47067\">-<\/span><span style=\"color: #6CB6FF\">1<\/span><span style=\"color: #ADBAC7\">;<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">        <\/span><span style=\"color: #F47067\">public<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #DCBDFB\">AppendCommand<\/span><span style=\"color: #ADBAC7\">(<\/span><span style=\"color: #F69D50\">DummyMusicPlayer<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #F69D50\">receiver<\/span><span style=\"color: #ADBAC7\">, <\/span><span style=\"color: #F69D50\">CommandStack<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #F69D50\">undoStack<\/span><span style=\"color: #ADBAC7\">)<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">        {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">            <\/span><span style=\"color: #6CB6FF\">this<\/span><span style=\"color: #ADBAC7\">.receiver <\/span><span style=\"color: #F47067\">=<\/span><span style=\"color: #ADBAC7\"> receiver;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">            <\/span><span style=\"color: #6CB6FF\">this<\/span><span style=\"color: #ADBAC7\">.undoStack <\/span><span style=\"color: #F47067\">=<\/span><span style=\"color: #ADBAC7\"> undoStack;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">        }<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">        <\/span><span style=\"color: #F47067\">public<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #F47067\">void<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #DCBDFB\">execute<\/span><span style=\"color: #ADBAC7\">()<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">        {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">            <\/span><span style=\"color: #F69D50\">String<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #F69D50\">song<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #F47067\">=<\/span><span style=\"color: #ADBAC7\"> DummyFileOpenDialog.<\/span><span style=\"color: #DCBDFB\">callFileOpenDlg<\/span><span style=\"color: #ADBAC7\">();<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">            idx <\/span><span style=\"color: #F47067\">=<\/span><span style=\"color: #ADBAC7\"> receiver.<\/span><span style=\"color: #DCBDFB\">append<\/span><span style=\"color: #ADBAC7\">(song);<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">            <\/span><span style=\"color: #F69D50\">AppendCommand<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #F69D50\">cmd<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #F47067\">=<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #F47067\">new<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #F69D50\">AppendCommand<\/span><span style=\"color: #ADBAC7\">(receiver, undoStack);<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">            cmd.idx <\/span><span style=\"color: #F47067\">=<\/span><span style=\"color: #ADBAC7\"> idx;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">            undoStack.<\/span><span style=\"color: #DCBDFB\">pushCmd<\/span><span style=\"color: #ADBAC7\">(cmd);<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">        }<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">        <\/span><span style=\"color: #F47067\">public<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #F47067\">void<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #DCBDFB\">undo<\/span><span style=\"color: #ADBAC7\">()<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">        {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">            <\/span><span style=\"color: #F47067\">if<\/span><span style=\"color: #ADBAC7\">(idx <\/span><span style=\"color: #F47067\">!=<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #F47067\">-<\/span><span style=\"color: #6CB6FF\">1<\/span><span style=\"color: #ADBAC7\">)<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">            {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">                receiver.<\/span><span style=\"color: #DCBDFB\">delete<\/span><span style=\"color: #ADBAC7\">(idx);<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">            }<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">        }<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">    }<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">    <\/span><span style=\"color: #F47067\">class<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #F69D50\">DeleteCommand<\/span><span style=\"color: #ADBAC7\"> : <\/span><span style=\"color: #F69D50\">ICommand<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">    {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">        <\/span><span style=\"color: #F47067\">private<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #F69D50\">DummyMusicPlayer<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #F69D50\">receiver<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #F47067\">=<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #6CB6FF\">null<\/span><span style=\"color: #ADBAC7\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">        <\/span><span style=\"color: #F47067\">private<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #F69D50\">CommandStack<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #F69D50\">undoStack<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #F47067\">=<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #6CB6FF\">null<\/span><span style=\"color: #ADBAC7\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">        <\/span><span style=\"color: #F47067\">private<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #F69D50\">String<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #F69D50\">song<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #F47067\">=<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #96D0FF\">&quot;&quot;<\/span><span style=\"color: #ADBAC7\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">        <\/span><span style=\"color: #F47067\">private<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #F47067\">int<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #F69D50\">idx<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #F47067\">=<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #F47067\">-<\/span><span style=\"color: #6CB6FF\">1<\/span><span style=\"color: #ADBAC7\">;<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">        <\/span><span style=\"color: #F47067\">public<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #DCBDFB\">DeleteCommand<\/span><span style=\"color: #ADBAC7\">(<\/span><span style=\"color: #F69D50\">DummyMusicPlayer<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #F69D50\">receiver<\/span><span style=\"color: #ADBAC7\">, <\/span><span style=\"color: #F69D50\">CommandStack<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #F69D50\">undoStack<\/span><span style=\"color: #ADBAC7\">)<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">        {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">            <\/span><span style=\"color: #6CB6FF\">this<\/span><span style=\"color: #ADBAC7\">.receiver <\/span><span style=\"color: #F47067\">=<\/span><span style=\"color: #ADBAC7\"> receiver;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">            <\/span><span style=\"color: #6CB6FF\">this<\/span><span style=\"color: #ADBAC7\">.undoStack <\/span><span style=\"color: #F47067\">=<\/span><span style=\"color: #ADBAC7\"> undoStack;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">        }<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">        <\/span><span style=\"color: #F47067\">public<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #F47067\">void<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #DCBDFB\">execute<\/span><span style=\"color: #ADBAC7\">()<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">        {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">            idx <\/span><span style=\"color: #F47067\">=<\/span><span style=\"color: #ADBAC7\"> receiver.Selected;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">            song <\/span><span style=\"color: #F47067\">=<\/span><span style=\"color: #ADBAC7\"> receiver.<\/span><span style=\"color: #DCBDFB\">delete<\/span><span style=\"color: #ADBAC7\">();<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">            <\/span><span style=\"color: #F69D50\">DeleteCommand<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #F69D50\">cmd<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #F47067\">=<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #F47067\">new<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #F69D50\">DeleteCommand<\/span><span style=\"color: #ADBAC7\">(receiver, undoStack);<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">            cmd.song <\/span><span style=\"color: #F47067\">=<\/span><span style=\"color: #ADBAC7\"> song;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">            cmd.idx <\/span><span style=\"color: #F47067\">=<\/span><span style=\"color: #ADBAC7\"> idx;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">            undoStack.<\/span><span style=\"color: #DCBDFB\">pushCmd<\/span><span style=\"color: #ADBAC7\">(cmd);<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">        }<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">        <\/span><span style=\"color: #F47067\">public<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #F47067\">void<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #DCBDFB\">undo<\/span><span style=\"color: #ADBAC7\">()<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">        {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">            <\/span><span style=\"color: #F47067\">if<\/span><span style=\"color: #ADBAC7\">(idx <\/span><span style=\"color: #F47067\">!=<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #F47067\">-<\/span><span style=\"color: #6CB6FF\">1<\/span><span style=\"color: #ADBAC7\">)<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">            {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">                receiver.<\/span><span style=\"color: #DCBDFB\">insert<\/span><span style=\"color: #ADBAC7\">(idx, song);<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">            }<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">        }<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">    }<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">    <\/span><span style=\"color: #F47067\">static<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #F47067\">class<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #F69D50\">DummyFileOpenDialog<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">    {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">        <\/span><span style=\"color: #F47067\">private<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #F47067\">static<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #F69D50\">List<\/span><span style=\"color: #ADBAC7\">&lt;<\/span><span style=\"color: #F69D50\">String<\/span><span style=\"color: #ADBAC7\">&gt; <\/span><span style=\"color: #F69D50\">testSongs<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #F47067\">=<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #F47067\">new<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #F69D50\">List<\/span><span style=\"color: #ADBAC7\">&lt;<\/span><span style=\"color: #F69D50\">String<\/span><span style=\"color: #ADBAC7\">&gt; { <\/span><span style=\"color: #96D0FF\">&quot;song1&quot;<\/span><span style=\"color: #ADBAC7\">, <\/span><span style=\"color: #96D0FF\">&quot;song2&quot;<\/span><span style=\"color: #ADBAC7\">, <\/span><span style=\"color: #96D0FF\">&quot;song3&quot;<\/span><span style=\"color: #ADBAC7\">, <\/span><span style=\"color: #96D0FF\">&quot;song4&quot;<\/span><span style=\"color: #ADBAC7\">, <\/span><span style=\"color: #96D0FF\">&quot;song5&quot;<\/span><span style=\"color: #ADBAC7\"> };<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">        <\/span><span style=\"color: #F47067\">private<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #F47067\">static<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #F47067\">int<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #F69D50\">fileOpenIdx<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #F47067\">=<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #6CB6FF\">0<\/span><span style=\"color: #ADBAC7\">;<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">        <\/span><span style=\"color: #F47067\">public<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #F47067\">static<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #F69D50\">String<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #DCBDFB\">callFileOpenDlg<\/span><span style=\"color: #ADBAC7\">()<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">        {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">            <\/span><span style=\"color: #F69D50\">String<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #F69D50\">song<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #F47067\">=<\/span><span style=\"color: #ADBAC7\"> testSongs&#91;fileOpenIdx&#93;;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">            fileOpenIdx<\/span><span style=\"color: #F47067\">++<\/span><span style=\"color: #ADBAC7\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">            <\/span><span style=\"color: #F47067\">if<\/span><span style=\"color: #ADBAC7\"> (fileOpenIdx <\/span><span style=\"color: #F47067\">&gt;=<\/span><span style=\"color: #ADBAC7\"> testSongs.<\/span><span style=\"color: #DCBDFB\">Count<\/span><span style=\"color: #ADBAC7\">()) fileOpenIdx <\/span><span style=\"color: #F47067\">=<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #6CB6FF\">0<\/span><span style=\"color: #ADBAC7\">;<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">            <\/span><span style=\"color: #F47067\">return<\/span><span style=\"color: #ADBAC7\"> song;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">        }<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">    }<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">    <\/span><span style=\"color: #F47067\">static<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #F47067\">class<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #F69D50\">Shuffle<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">    {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">        <\/span><span style=\"color: #F47067\">private<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #F47067\">static<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #F69D50\">Random<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #F69D50\">rng<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #F47067\">=<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #F47067\">new<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #F69D50\">Random<\/span><span style=\"color: #ADBAC7\">();<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">        <\/span><span style=\"color: #F47067\">public<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #F47067\">static<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #F47067\">void<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #DCBDFB\">shuffle<\/span><span style=\"color: #ADBAC7\">&lt;<\/span><span style=\"color: #F69D50\">T<\/span><span style=\"color: #ADBAC7\">&gt;(<\/span><span style=\"color: #F47067\">this<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #F69D50\">IList<\/span><span style=\"color: #ADBAC7\">&lt;<\/span><span style=\"color: #F69D50\">T<\/span><span style=\"color: #ADBAC7\">&gt; <\/span><span style=\"color: #F69D50\">list<\/span><span style=\"color: #ADBAC7\">)<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">        {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">            <\/span><span style=\"color: #F47067\">int<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #F69D50\">n<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #F47067\">=<\/span><span style=\"color: #ADBAC7\"> list.Count;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">            <\/span><span style=\"color: #F47067\">while<\/span><span style=\"color: #ADBAC7\"> (n <\/span><span style=\"color: #F47067\">&gt;<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #6CB6FF\">1<\/span><span style=\"color: #ADBAC7\">)<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">            {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">                n<\/span><span style=\"color: #F47067\">--<\/span><span style=\"color: #ADBAC7\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">                <\/span><span style=\"color: #F47067\">int<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #F69D50\">k<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #F47067\">=<\/span><span style=\"color: #ADBAC7\"> rng.<\/span><span style=\"color: #DCBDFB\">Next<\/span><span style=\"color: #ADBAC7\">(n <\/span><span style=\"color: #F47067\">+<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #6CB6FF\">1<\/span><span style=\"color: #ADBAC7\">);<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">                <\/span><span style=\"color: #F69D50\">T<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #F69D50\">value<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #F47067\">=<\/span><span style=\"color: #ADBAC7\"> list&#91;k&#93;;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">                list&#91;k&#93; <\/span><span style=\"color: #F47067\">=<\/span><span style=\"color: #ADBAC7\"> list&#91;n&#93;;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">                list&#91;n&#93; <\/span><span style=\"color: #F47067\">=<\/span><span style=\"color: #ADBAC7\"> value;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">            }<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">        }<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">    }<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">}<\/span><\/span>\n<span class=\"line\"><\/span><\/code><\/pre><\/div>\n\n\n\n<p>Command \ud074\ub798\uc2a4\uc758 \uad6c\ud604\uc740 \ub354 \uae38\uc5b4\uc84c\ub2e4. shuffle\uc744 \uc9c0\uc6d0\ud574\uc8fc\ub294 Kotlin\uc774\ub098 Python\uacfc \ub2ec\ub9ac \uc9c1\uc811 \uad6c\ud604\ud588\ub2e4. ( <a href=\"https:\/\/stackoverflow.com\/questions\/273313\/randomize-a-listt\">\uad00\ub828 stackoverflow \ucc38\uc870<\/a> ) <\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers\" data-code-block-pro-font-family=\"Code-Pro-Roboto-Mono.ttf\" style=\"font-size:clamp(14px, .875rem, 21px);font-family:Code-Pro-Roboto-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#adbac7;--cbp-line-number-width:calc(2 * 0.6 * .875rem);line-height:clamp(20px, 1.25rem, 30px);--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#22272e\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"54\" height=\"14\" viewBox=\"0 0 54 14\"><g fill=\"none\" fill-rule=\"evenodd\" transform=\"translate(1 1)\"><circle cx=\"6\" cy=\"6\" r=\"6\" fill=\"#FF5F56\" stroke=\"#E0443E\" stroke-width=\".5\"><\/circle><circle cx=\"26\" cy=\"6\" r=\"6\" fill=\"#FFBD2E\" stroke=\"#DEA123\" stroke-width=\".5\"><\/circle><circle cx=\"46\" cy=\"6\" r=\"6\" fill=\"#27C93F\" stroke=\"#1AAB29\" stroke-width=\".5\"><\/circle><\/g><\/svg><\/span><span role=\"button\" tabindex=\"0\" style=\"color:#adbac7;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><pre class=\"code-block-pro-copy-button-pre\" aria-hidden=\"true\"><textarea class=\"code-block-pro-copy-button-textarea\" tabindex=\"-1\" aria-hidden=\"true\" readonly>using System.Collections.Generic;\nusing UnityEngine;\n\nnamespace command\n{\n    public class cmdmain : MonoBehaviour\n    {\n        \/\/ Start is called before the first frame update\n        void Start()\n        {\n            DummyMusicPlayer musicPlayer = new DummyMusicPlayer();\n            CommandStack undoStack = new CommandStack();\n\n            ICommand addCmd = new AppendCommand(musicPlayer, undoStack);\n            ICommand delCmd = new DeleteCommand(musicPlayer, undoStack);\n            ICommand shuffleCmd = new ShuffleCommand(musicPlayer, undoStack);\n\n            DummyButton addButton = new DummyButton(\"ADD\");\n            addButton.assignCommand(addCmd);\n            DummyButton deleteButton = new DummyButton(\"DELETE\");\n            deleteButton.assignCommand(delCmd);\n            DummyButton shuffleButton = new DummyButton(\"SHUFFLE\");\n            shuffleButton.assignCommand(shuffleCmd);\n\n            addButton.pressed();\n            addButton.pressed();\n            addButton.pressed();\n            addButton.pressed();\n            addButton.pressed();\n            print(\"add test\");\n            printList(musicPlayer.Playlist);\n\n            shuffleButton.pressed();\n            print(\"shuffle test\");\n            printList(musicPlayer.Playlist);\n\n            musicPlayer.Selected = 3;\n            deleteButton.pressed();\n            musicPlayer.Selected = 0;\n            deleteButton.pressed();\n            print(\"delete test\");\n            printList(musicPlayer.Playlist);\n\n            print(\"undo test\");\n            undoStack.undo();\n            printList(musicPlayer.Playlist);\n            undoStack.undo();\n            printList(musicPlayer.Playlist);\n            undoStack.undo();\n            printList(musicPlayer.Playlist);\n            undoStack.undo();\n            printList(musicPlayer.Playlist);\n            undoStack.undo();\n            printList(musicPlayer.Playlist);\n        }\n\n        \/\/ Update is called once per frame\n        void Update()\n        {\n\n        }\n\n        void printList&lt;T>(List&lt;T> mylist)\n        {\n            string result = \"\";\n            foreach(var item in mylist)\n            {\n                result += item.ToString() + \", \";\n            }\n\n            print(result);\n        }\n    }\n\n}\n<\/textarea><\/pre><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki github-dark-dimmed\" style=\"background-color: #22272e\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #F47067\">using<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #F69D50\">System<\/span><span style=\"color: #ADBAC7\">.<\/span><span style=\"color: #F69D50\">Collections<\/span><span style=\"color: #ADBAC7\">.<\/span><span style=\"color: #F69D50\">Generic<\/span><span style=\"color: #ADBAC7\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F47067\">using<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #F69D50\">UnityEngine<\/span><span style=\"color: #ADBAC7\">;<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #F47067\">namespace<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #F69D50\">command<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">{<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">    <\/span><span style=\"color: #F47067\">public<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #F47067\">class<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #F69D50\">cmdmain<\/span><span style=\"color: #ADBAC7\"> : <\/span><span style=\"color: #F69D50\">MonoBehaviour<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">    {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #768390\">        \/\/ Start is called before the first frame update<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">        <\/span><span style=\"color: #F47067\">void<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #DCBDFB\">Start<\/span><span style=\"color: #ADBAC7\">()<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">        {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">            <\/span><span style=\"color: #F69D50\">DummyMusicPlayer<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #F69D50\">musicPlayer<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #F47067\">=<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #F47067\">new<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #F69D50\">DummyMusicPlayer<\/span><span style=\"color: #ADBAC7\">();<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">            <\/span><span style=\"color: #F69D50\">CommandStack<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #F69D50\">undoStack<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #F47067\">=<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #F47067\">new<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #F69D50\">CommandStack<\/span><span style=\"color: #ADBAC7\">();<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">            <\/span><span style=\"color: #F69D50\">ICommand<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #F69D50\">addCmd<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #F47067\">=<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #F47067\">new<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #F69D50\">AppendCommand<\/span><span style=\"color: #ADBAC7\">(musicPlayer, undoStack);<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">            <\/span><span style=\"color: #F69D50\">ICommand<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #F69D50\">delCmd<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #F47067\">=<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #F47067\">new<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #F69D50\">DeleteCommand<\/span><span style=\"color: #ADBAC7\">(musicPlayer, undoStack);<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">            <\/span><span style=\"color: #F69D50\">ICommand<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #F69D50\">shuffleCmd<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #F47067\">=<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #F47067\">new<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #F69D50\">ShuffleCommand<\/span><span style=\"color: #ADBAC7\">(musicPlayer, undoStack);<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">            <\/span><span style=\"color: #F69D50\">DummyButton<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #F69D50\">addButton<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #F47067\">=<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #F47067\">new<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #F69D50\">DummyButton<\/span><span style=\"color: #ADBAC7\">(<\/span><span style=\"color: #96D0FF\">&quot;ADD&quot;<\/span><span style=\"color: #ADBAC7\">);<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">            addButton.<\/span><span style=\"color: #DCBDFB\">assignCommand<\/span><span style=\"color: #ADBAC7\">(addCmd);<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">            <\/span><span style=\"color: #F69D50\">DummyButton<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #F69D50\">deleteButton<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #F47067\">=<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #F47067\">new<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #F69D50\">DummyButton<\/span><span style=\"color: #ADBAC7\">(<\/span><span style=\"color: #96D0FF\">&quot;DELETE&quot;<\/span><span style=\"color: #ADBAC7\">);<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">            deleteButton.<\/span><span style=\"color: #DCBDFB\">assignCommand<\/span><span style=\"color: #ADBAC7\">(delCmd);<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">            <\/span><span style=\"color: #F69D50\">DummyButton<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #F69D50\">shuffleButton<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #F47067\">=<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #F47067\">new<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #F69D50\">DummyButton<\/span><span style=\"color: #ADBAC7\">(<\/span><span style=\"color: #96D0FF\">&quot;SHUFFLE&quot;<\/span><span style=\"color: #ADBAC7\">);<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">            shuffleButton.<\/span><span style=\"color: #DCBDFB\">assignCommand<\/span><span style=\"color: #ADBAC7\">(shuffleCmd);<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">            addButton.<\/span><span style=\"color: #DCBDFB\">pressed<\/span><span style=\"color: #ADBAC7\">();<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">            addButton.<\/span><span style=\"color: #DCBDFB\">pressed<\/span><span style=\"color: #ADBAC7\">();<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">            addButton.<\/span><span style=\"color: #DCBDFB\">pressed<\/span><span style=\"color: #ADBAC7\">();<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">            addButton.<\/span><span style=\"color: #DCBDFB\">pressed<\/span><span style=\"color: #ADBAC7\">();<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">            addButton.<\/span><span style=\"color: #DCBDFB\">pressed<\/span><span style=\"color: #ADBAC7\">();<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">            <\/span><span style=\"color: #DCBDFB\">print<\/span><span style=\"color: #ADBAC7\">(<\/span><span style=\"color: #96D0FF\">&quot;add test&quot;<\/span><span style=\"color: #ADBAC7\">);<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">            <\/span><span style=\"color: #DCBDFB\">printList<\/span><span style=\"color: #ADBAC7\">(musicPlayer.Playlist);<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">            shuffleButton.<\/span><span style=\"color: #DCBDFB\">pressed<\/span><span style=\"color: #ADBAC7\">();<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">            <\/span><span style=\"color: #DCBDFB\">print<\/span><span style=\"color: #ADBAC7\">(<\/span><span style=\"color: #96D0FF\">&quot;shuffle test&quot;<\/span><span style=\"color: #ADBAC7\">);<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">            <\/span><span style=\"color: #DCBDFB\">printList<\/span><span style=\"color: #ADBAC7\">(musicPlayer.Playlist);<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">            musicPlayer.Selected <\/span><span style=\"color: #F47067\">=<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #6CB6FF\">3<\/span><span style=\"color: #ADBAC7\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">            deleteButton.<\/span><span style=\"color: #DCBDFB\">pressed<\/span><span style=\"color: #ADBAC7\">();<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">            musicPlayer.Selected <\/span><span style=\"color: #F47067\">=<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #6CB6FF\">0<\/span><span style=\"color: #ADBAC7\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">            deleteButton.<\/span><span style=\"color: #DCBDFB\">pressed<\/span><span style=\"color: #ADBAC7\">();<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">            <\/span><span style=\"color: #DCBDFB\">print<\/span><span style=\"color: #ADBAC7\">(<\/span><span style=\"color: #96D0FF\">&quot;delete test&quot;<\/span><span style=\"color: #ADBAC7\">);<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">            <\/span><span style=\"color: #DCBDFB\">printList<\/span><span style=\"color: #ADBAC7\">(musicPlayer.Playlist);<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">            <\/span><span style=\"color: #DCBDFB\">print<\/span><span style=\"color: #ADBAC7\">(<\/span><span style=\"color: #96D0FF\">&quot;undo test&quot;<\/span><span style=\"color: #ADBAC7\">);<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">            undoStack.<\/span><span style=\"color: #DCBDFB\">undo<\/span><span style=\"color: #ADBAC7\">();<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">            <\/span><span style=\"color: #DCBDFB\">printList<\/span><span style=\"color: #ADBAC7\">(musicPlayer.Playlist);<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">            undoStack.<\/span><span style=\"color: #DCBDFB\">undo<\/span><span style=\"color: #ADBAC7\">();<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">            <\/span><span style=\"color: #DCBDFB\">printList<\/span><span style=\"color: #ADBAC7\">(musicPlayer.Playlist);<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">            undoStack.<\/span><span style=\"color: #DCBDFB\">undo<\/span><span style=\"color: #ADBAC7\">();<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">            <\/span><span style=\"color: #DCBDFB\">printList<\/span><span style=\"color: #ADBAC7\">(musicPlayer.Playlist);<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">            undoStack.<\/span><span style=\"color: #DCBDFB\">undo<\/span><span style=\"color: #ADBAC7\">();<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">            <\/span><span style=\"color: #DCBDFB\">printList<\/span><span style=\"color: #ADBAC7\">(musicPlayer.Playlist);<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">            undoStack.<\/span><span style=\"color: #DCBDFB\">undo<\/span><span style=\"color: #ADBAC7\">();<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">            <\/span><span style=\"color: #DCBDFB\">printList<\/span><span style=\"color: #ADBAC7\">(musicPlayer.Playlist);<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">        }<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #768390\">        \/\/ Update is called once per frame<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">        <\/span><span style=\"color: #F47067\">void<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #DCBDFB\">Update<\/span><span style=\"color: #ADBAC7\">()<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">        {<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">        }<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">        <\/span><span style=\"color: #F47067\">void<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #DCBDFB\">printList<\/span><span style=\"color: #ADBAC7\">&lt;<\/span><span style=\"color: #F69D50\">T<\/span><span style=\"color: #ADBAC7\">&gt;(<\/span><span style=\"color: #F69D50\">List<\/span><span style=\"color: #ADBAC7\">&lt;<\/span><span style=\"color: #F69D50\">T<\/span><span style=\"color: #ADBAC7\">&gt; <\/span><span style=\"color: #F69D50\">mylist<\/span><span style=\"color: #ADBAC7\">)<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">        {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">            <\/span><span style=\"color: #F47067\">string<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #F69D50\">result<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #F47067\">=<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #96D0FF\">&quot;&quot;<\/span><span style=\"color: #ADBAC7\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">            <\/span><span style=\"color: #F47067\">foreach<\/span><span style=\"color: #ADBAC7\">(<\/span><span style=\"color: #F47067\">var<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #F69D50\">item<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #F47067\">in<\/span><span style=\"color: #ADBAC7\"> mylist)<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">            {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">                result <\/span><span style=\"color: #F47067\">+=<\/span><span style=\"color: #ADBAC7\"> item.<\/span><span style=\"color: #DCBDFB\">ToString<\/span><span style=\"color: #ADBAC7\">() <\/span><span style=\"color: #F47067\">+<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #96D0FF\">&quot;, &quot;<\/span><span style=\"color: #ADBAC7\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">            }<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">            <\/span><span style=\"color: #DCBDFB\">print<\/span><span style=\"color: #ADBAC7\">(result);<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">        }<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">    }<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">}<\/span><\/span>\n<span class=\"line\"><\/span><\/code><\/pre><\/div>\n\n\n\n<p>\ud14c\uc2a4\ud2b8 \ud074\ub77c\uc774\uc5b8\ud2b8 \ud074\ub798\uc2a4. \uc720\ub2c8\ud2f0\uc0c1\uc774\uae30 \ub54c\ubb38\uc5d0 main\uc774 \uc5c6\uace0, empty obejct \uc0dd\uc131\ud574\uc11c \uc704 \ucef4\ud3ec\ub10c\ud2b8\ub97c \ucd94\uac00\ud574 \uc2e4\ud589\ud588\ub2e4. \ub2e4\ub978\uc5b8\uc5b4\uc640 \ub2ec\ub9ac, array\ub098 list\ub97c \uc81c\ub300\ub85c \ucd9c\ub825\ud574\uc8fc\uc9c0 \uc54a\uc544, \ub9ac\uc2a4\ud2b8 \uc544\uc774\ud15c\uc744 \ud55c\uc904\ub85c \ucd9c\ub825\ud558\ub294 printList \uba54\uc18c\ub4dc\ub97c \uad6c\ud604\ud588\ub2e4. \uadf8 \uacb0\uacfc\ub294 \ub2e4\uc74c\uacfc \uac19\ub2e4.<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"307\" height=\"466\" src=\"http:\/\/batmask.dothome.co.kr\/wordpress\/wp-content\/uploads\/2020\/05\/command_result.png\" alt=\"\" class=\"wp-image-590\" srcset=\"http:\/\/batmask.net\/wordpress\/wp-content\/uploads\/2020\/05\/command_result.png 307w, http:\/\/batmask.net\/wordpress\/wp-content\/uploads\/2020\/05\/command_result-198x300.png 198w\" sizes=\"auto, (max-width: 307px) 100vw, 307px\" \/><\/figure>\n<\/div>\n\n\n<p>\uc798 \ub3d9\uc791\ud558\ub294 \uac83\uc744 \ud655\uc778. <\/p>\n\n\n\n<hr class=\"wp-block-separator has-css-opacity is-style-dots\"\/>\n\n\n\n<h3 class=\"wp-block-heading\">Python<\/h3>\n\n\n\n<p>\ud30c\uc774\uc36c \uad6c\ud604\uc740 \ub2e4\uc74c\uacfc \uac19\ub2e4. \uc6b0\uc120 Receiver\uc5d0 \ud574\ub2f9\ud558\ub294 DummyMusicPlayer\uc758 \uad6c\ud604\uc774\ub2e4.<\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers\" data-code-block-pro-font-family=\"Code-Pro-Roboto-Mono.ttf\" style=\"font-size:clamp(14px, .875rem, 21px);font-family:Code-Pro-Roboto-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#adbac7;--cbp-line-number-width:calc(2 * 0.6 * .875rem);line-height:clamp(20px, 1.25rem, 30px);--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#22272e\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"54\" height=\"14\" viewBox=\"0 0 54 14\"><g fill=\"none\" fill-rule=\"evenodd\" transform=\"translate(1 1)\"><circle cx=\"6\" cy=\"6\" r=\"6\" fill=\"#FF5F56\" stroke=\"#E0443E\" stroke-width=\".5\"><\/circle><circle cx=\"26\" cy=\"6\" r=\"6\" fill=\"#FFBD2E\" stroke=\"#DEA123\" stroke-width=\".5\"><\/circle><circle cx=\"46\" cy=\"6\" r=\"6\" fill=\"#27C93F\" stroke=\"#1AAB29\" stroke-width=\".5\"><\/circle><\/g><\/svg><\/span><span role=\"button\" tabindex=\"0\" style=\"color:#adbac7;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><pre class=\"code-block-pro-copy-button-pre\" aria-hidden=\"true\"><textarea class=\"code-block-pro-copy-button-textarea\" tabindex=\"-1\" aria-hidden=\"true\" readonly>from typing import List\n\nclass DummyMusicPlayer:\n    def __init__(self):\n        self._playlist: List&#91;str&#93; = []\n        self._selected_idx = 0\n\n    @property\n    def selected(self):\n        return self._selected_idx\n\n    @selected.setter\n    def selected(self, value: int):\n        self._selected_idx = value\n\n    @property\n    def playlist(self):\n        return self._playlist\n\n    @playlist.setter\n    def playlist(self, new_list: List&#91;str&#93;):\n        self._playlist = new_list\n\n    def clear_playlist(self):\n        self._playlist.clear()\n\n    def append(self, song: str) -> int:\n        self._playlist.append(song)\n        return len(self._playlist) - 1\n\n    def insert(self, idx: int, song: str):\n        self._playlist.insert(idx, song)\n\n    def delete(self, idx: int = -1) -> str:\n        song: str = \"\"\n        if idx == -1:\n            song = self._playlist&#91;self.selected&#93;\n            del self._playlist&#91;self.selected&#93;\n\n        else:\n            song = self._playlist&#91;idx&#93;\n            del self._playlist&#91;idx&#93;\n\n        return song\n\n\n<\/textarea><\/pre><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki github-dark-dimmed\" style=\"background-color: #22272e\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #F47067\">from<\/span><span style=\"color: #ADBAC7\"> typing <\/span><span style=\"color: #F47067\">import<\/span><span style=\"color: #ADBAC7\"> List<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #F47067\">class<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #F69D50\">DummyMusicPlayer<\/span><span style=\"color: #ADBAC7\">:<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">    <\/span><span style=\"color: #F47067\">def<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #6CB6FF\">__init__<\/span><span style=\"color: #ADBAC7\">(self):<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">        <\/span><span style=\"color: #6CB6FF\">self<\/span><span style=\"color: #ADBAC7\">._playlist: List&#91;<\/span><span style=\"color: #6CB6FF\">str<\/span><span style=\"color: #ADBAC7\">&#93; <\/span><span style=\"color: #F47067\">=<\/span><span style=\"color: #ADBAC7\"> []<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">        <\/span><span style=\"color: #6CB6FF\">self<\/span><span style=\"color: #ADBAC7\">._selected_idx <\/span><span style=\"color: #F47067\">=<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #6CB6FF\">0<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">    <\/span><span style=\"color: #DCBDFB\">@<\/span><span style=\"color: #6CB6FF\">property<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">    <\/span><span style=\"color: #F47067\">def<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #DCBDFB\">selected<\/span><span style=\"color: #ADBAC7\">(self):<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">        <\/span><span style=\"color: #F47067\">return<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #6CB6FF\">self<\/span><span style=\"color: #ADBAC7\">._selected_idx<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">    <\/span><span style=\"color: #DCBDFB\">@selected.setter<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">    <\/span><span style=\"color: #F47067\">def<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #DCBDFB\">selected<\/span><span style=\"color: #ADBAC7\">(self, value: <\/span><span style=\"color: #6CB6FF\">int<\/span><span style=\"color: #ADBAC7\">):<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">        <\/span><span style=\"color: #6CB6FF\">self<\/span><span style=\"color: #ADBAC7\">._selected_idx <\/span><span style=\"color: #F47067\">=<\/span><span style=\"color: #ADBAC7\"> value<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">    <\/span><span style=\"color: #DCBDFB\">@<\/span><span style=\"color: #6CB6FF\">property<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">    <\/span><span style=\"color: #F47067\">def<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #DCBDFB\">playlist<\/span><span style=\"color: #ADBAC7\">(self):<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">        <\/span><span style=\"color: #F47067\">return<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #6CB6FF\">self<\/span><span style=\"color: #ADBAC7\">._playlist<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">    <\/span><span style=\"color: #DCBDFB\">@playlist.setter<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">    <\/span><span style=\"color: #F47067\">def<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #DCBDFB\">playlist<\/span><span style=\"color: #ADBAC7\">(self, new_list: List&#91;<\/span><span style=\"color: #6CB6FF\">str<\/span><span style=\"color: #ADBAC7\">&#93;):<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">        <\/span><span style=\"color: #6CB6FF\">self<\/span><span style=\"color: #ADBAC7\">._playlist <\/span><span style=\"color: #F47067\">=<\/span><span style=\"color: #ADBAC7\"> new_list<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">    <\/span><span style=\"color: #F47067\">def<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #DCBDFB\">clear_playlist<\/span><span style=\"color: #ADBAC7\">(self):<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">        <\/span><span style=\"color: #6CB6FF\">self<\/span><span style=\"color: #ADBAC7\">._playlist.clear()<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">    <\/span><span style=\"color: #F47067\">def<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #DCBDFB\">append<\/span><span style=\"color: #ADBAC7\">(self, song: <\/span><span style=\"color: #6CB6FF\">str<\/span><span style=\"color: #ADBAC7\">) -&gt; <\/span><span style=\"color: #6CB6FF\">int<\/span><span style=\"color: #ADBAC7\">:<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">        <\/span><span style=\"color: #6CB6FF\">self<\/span><span style=\"color: #ADBAC7\">._playlist.append(song)<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">        <\/span><span style=\"color: #F47067\">return<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #6CB6FF\">len<\/span><span style=\"color: #ADBAC7\">(<\/span><span style=\"color: #6CB6FF\">self<\/span><span style=\"color: #ADBAC7\">._playlist) <\/span><span style=\"color: #F47067\">-<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #6CB6FF\">1<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">    <\/span><span style=\"color: #F47067\">def<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #DCBDFB\">insert<\/span><span style=\"color: #ADBAC7\">(self, idx: <\/span><span style=\"color: #6CB6FF\">int<\/span><span style=\"color: #ADBAC7\">, song: <\/span><span style=\"color: #6CB6FF\">str<\/span><span style=\"color: #ADBAC7\">):<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">        <\/span><span style=\"color: #6CB6FF\">self<\/span><span style=\"color: #ADBAC7\">._playlist.insert(idx, song)<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">    <\/span><span style=\"color: #F47067\">def<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #DCBDFB\">delete<\/span><span style=\"color: #ADBAC7\">(self, idx: <\/span><span style=\"color: #6CB6FF\">int<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #F47067\">=<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #F47067\">-<\/span><span style=\"color: #6CB6FF\">1<\/span><span style=\"color: #ADBAC7\">) -&gt; <\/span><span style=\"color: #6CB6FF\">str<\/span><span style=\"color: #ADBAC7\">:<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">        song: <\/span><span style=\"color: #6CB6FF\">str<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #F47067\">=<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #96D0FF\">&quot;&quot;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">        <\/span><span style=\"color: #F47067\">if<\/span><span style=\"color: #ADBAC7\"> idx <\/span><span style=\"color: #F47067\">==<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #F47067\">-<\/span><span style=\"color: #6CB6FF\">1<\/span><span style=\"color: #ADBAC7\">:<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">            song <\/span><span style=\"color: #F47067\">=<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #6CB6FF\">self<\/span><span style=\"color: #ADBAC7\">._playlist&#91;<\/span><span style=\"color: #6CB6FF\">self<\/span><span style=\"color: #ADBAC7\">.selected&#93;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">            <\/span><span style=\"color: #F47067\">del<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #6CB6FF\">self<\/span><span style=\"color: #ADBAC7\">._playlist&#91;<\/span><span style=\"color: #6CB6FF\">self<\/span><span style=\"color: #ADBAC7\">.selected&#93;<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">        <\/span><span style=\"color: #F47067\">else<\/span><span style=\"color: #ADBAC7\">:<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">            song <\/span><span style=\"color: #F47067\">=<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #6CB6FF\">self<\/span><span style=\"color: #ADBAC7\">._playlist&#91;idx&#93;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">            <\/span><span style=\"color: #F47067\">del<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #6CB6FF\">self<\/span><span style=\"color: #ADBAC7\">._playlist&#91;idx&#93;<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">        <\/span><span style=\"color: #F47067\">return<\/span><span style=\"color: #ADBAC7\"> song<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><\/span><\/code><\/pre><\/div>\n\n\n\n<p>\uc55e\uc11c, Kotlin\uc5d0\uc11c property\ub97c \uc81c\ub300\ub85c \uc0ac\uc6a9\ud558\uc9c0 \ubabb\ud55c\uac70 \uac19\uc544, property\ub97c \uc801\uc6a9\ud574 \uac1c\uc120\ud588\ub2e4. Command\ub098 Invoker\uc5d0 \uc758\uc874\uc131\uc774 \uc5c6\ub294 \ub3c5\ub9bd\uc801\uc778 \ucf54\ub4dc\uc784\uc744 \uc54c \uc218 \uc788\ub2e4. <\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers\" data-code-block-pro-font-family=\"Code-Pro-Roboto-Mono.ttf\" style=\"font-size:clamp(14px, .875rem, 21px);font-family:Code-Pro-Roboto-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#adbac7;--cbp-line-number-width:calc(1 * 0.6 * .875rem);line-height:clamp(20px, 1.25rem, 30px);--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#22272e\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"54\" height=\"14\" viewBox=\"0 0 54 14\"><g fill=\"none\" fill-rule=\"evenodd\" transform=\"translate(1 1)\"><circle cx=\"6\" cy=\"6\" r=\"6\" fill=\"#FF5F56\" stroke=\"#E0443E\" stroke-width=\".5\"><\/circle><circle cx=\"26\" cy=\"6\" r=\"6\" fill=\"#FFBD2E\" stroke=\"#DEA123\" stroke-width=\".5\"><\/circle><circle cx=\"46\" cy=\"6\" r=\"6\" fill=\"#27C93F\" stroke=\"#1AAB29\" stroke-width=\".5\"><\/circle><\/g><\/svg><\/span><span role=\"button\" tabindex=\"0\" style=\"color:#adbac7;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><pre class=\"code-block-pro-copy-button-pre\" aria-hidden=\"true\"><textarea class=\"code-block-pro-copy-button-textarea\" tabindex=\"-1\" aria-hidden=\"true\" readonly>class ICommand:\n    def execute(self):\n        raise NotImplementedError\n\n    def undo(self):\n        raise NotImplementedError\n<\/textarea><\/pre><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki github-dark-dimmed\" style=\"background-color: #22272e\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #F47067\">class<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #F69D50\">ICommand<\/span><span style=\"color: #ADBAC7\">:<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">    <\/span><span style=\"color: #F47067\">def<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #DCBDFB\">execute<\/span><span style=\"color: #ADBAC7\">(self):<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">        <\/span><span style=\"color: #F47067\">raise<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #6CB6FF\">NotImplementedError<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">    <\/span><span style=\"color: #F47067\">def<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #DCBDFB\">undo<\/span><span style=\"color: #ADBAC7\">(self):<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">        <\/span><span style=\"color: #F47067\">raise<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #6CB6FF\">NotImplementedError<\/span><\/span>\n<span class=\"line\"><\/span><\/code><\/pre><\/div>\n\n\n\n<p>Command \uc778\ud130\ud398\uc774\uc2a4\ub97c \ubcc4\ub3c4 \ud30c\uc77c\ub85c \uad6c\ud604\ud588\ub2e4. \uc778\ud130\ud398\uc774\uc2a4\ub9cc \ubd84\ub9ac\ud55c\uac74, python\uc758 circular import\ub97c \ud53c\ud558\uae30 \uc704\ud55c \uac83\uc774\uae30\ub3c4 \ud558\ub2e4. \ub2e4\uc74c\uc5d0 \ub098\uc62c CommandStack\uacfc \uac01 Command\ub4e4\uc774 \uc0c1\ud638\ucc38\uc870\ud558\uae30 \ub54c\ubb38\uc5d0 \uc11c\ub85c \uc784\ud3ec\ud2b8 \ud558\ub294\uacbd\uc6b0, circular import \ubb38\uc81c\uac00 \ubc1c\uc0dd\ud55c\ub2e4. \uc774\ub97c \ud53c\ud558\ub294 \ud3b8\ubc95\uac19\uc740 \ubc29\ubc95\ub4e4\uc774 \uc788\uc73c\ub098, CommandStack\uc744 \ucc38\uc870\ud558\uc9c0 \uc54a\ub294 \uc778\ud130\ud398\uc774\uc2a4\ub97c \ubd84\ub9ac\uc2dc\ud0a4\uba74, \uc0c1\ud638\ucc38\uc870\ub97c \ubc97\uc5b4\ub098\uae30 \ub54c\ubb38\uc5d0 \uc774\uac8c \ub354 \uae54\ub054\ud558\ub2e4.<\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers\" data-code-block-pro-font-family=\"Code-Pro-Roboto-Mono.ttf\" style=\"font-size:clamp(14px, .875rem, 21px);font-family:Code-Pro-Roboto-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#adbac7;--cbp-line-number-width:calc(2 * 0.6 * .875rem);line-height:clamp(20px, 1.25rem, 30px);--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#22272e\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"54\" height=\"14\" viewBox=\"0 0 54 14\"><g fill=\"none\" fill-rule=\"evenodd\" transform=\"translate(1 1)\"><circle cx=\"6\" cy=\"6\" r=\"6\" fill=\"#FF5F56\" stroke=\"#E0443E\" stroke-width=\".5\"><\/circle><circle cx=\"26\" cy=\"6\" r=\"6\" fill=\"#FFBD2E\" stroke=\"#DEA123\" stroke-width=\".5\"><\/circle><circle cx=\"46\" cy=\"6\" r=\"6\" fill=\"#27C93F\" stroke=\"#1AAB29\" stroke-width=\".5\"><\/circle><\/g><\/svg><\/span><span role=\"button\" tabindex=\"0\" style=\"color:#adbac7;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><pre class=\"code-block-pro-copy-button-pre\" aria-hidden=\"true\"><textarea class=\"code-block-pro-copy-button-textarea\" tabindex=\"-1\" aria-hidden=\"true\" readonly>from typing import List\n\nfrom command.ICommand import ICommand\n\n\nclass CommandStack:\n    def __init__(self):\n        self._command_stack: List&#91;ICommand&#93; = []\n\n    def push_cmd(self, cmd):\n        self._command_stack.append(cmd)\n\n    def _pop_cmd(self) -> ICommand:\n        if len(self._command_stack) > 0:\n            return self._command_stack.pop()\n        else:\n            return None\n\n    def undo(self):\n        cmd = self._pop_cmd()\n        cmd.undo()\n\n\n<\/textarea><\/pre><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki github-dark-dimmed\" style=\"background-color: #22272e\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #F47067\">from<\/span><span style=\"color: #ADBAC7\"> typing <\/span><span style=\"color: #F47067\">import<\/span><span style=\"color: #ADBAC7\"> List<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #F47067\">from<\/span><span style=\"color: #ADBAC7\"> command.ICommand <\/span><span style=\"color: #F47067\">import<\/span><span style=\"color: #ADBAC7\"> ICommand<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #F47067\">class<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #F69D50\">CommandStack<\/span><span style=\"color: #ADBAC7\">:<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">    <\/span><span style=\"color: #F47067\">def<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #6CB6FF\">__init__<\/span><span style=\"color: #ADBAC7\">(self):<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">        <\/span><span style=\"color: #6CB6FF\">self<\/span><span style=\"color: #ADBAC7\">._command_stack: List&#91;ICommand&#93; <\/span><span style=\"color: #F47067\">=<\/span><span style=\"color: #ADBAC7\"> []<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">    <\/span><span style=\"color: #F47067\">def<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #DCBDFB\">push_cmd<\/span><span style=\"color: #ADBAC7\">(self, cmd):<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">        <\/span><span style=\"color: #6CB6FF\">self<\/span><span style=\"color: #ADBAC7\">._command_stack.append(cmd)<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">    <\/span><span style=\"color: #F47067\">def<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #DCBDFB\">_pop_cmd<\/span><span style=\"color: #ADBAC7\">(self) -&gt; ICommand:<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">        <\/span><span style=\"color: #F47067\">if<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #6CB6FF\">len<\/span><span style=\"color: #ADBAC7\">(<\/span><span style=\"color: #6CB6FF\">self<\/span><span style=\"color: #ADBAC7\">._command_stack) <\/span><span style=\"color: #F47067\">&gt;<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #6CB6FF\">0<\/span><span style=\"color: #ADBAC7\">:<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">            <\/span><span style=\"color: #F47067\">return<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #6CB6FF\">self<\/span><span style=\"color: #ADBAC7\">._command_stack.pop()<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">        <\/span><span style=\"color: #F47067\">else<\/span><span style=\"color: #ADBAC7\">:<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">            <\/span><span style=\"color: #F47067\">return<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #6CB6FF\">None<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">    <\/span><span style=\"color: #F47067\">def<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #DCBDFB\">undo<\/span><span style=\"color: #ADBAC7\">(self):<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">        cmd <\/span><span style=\"color: #F47067\">=<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #6CB6FF\">self<\/span><span style=\"color: #ADBAC7\">._pop_cmd()<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">        cmd.undo()<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><\/span><\/code><\/pre><\/div>\n\n\n\n<p>\ucee4\ub9e8\ub4dc undo\ub97c \uc704\ud574 \uc800\uc7a5\ud560 stack\uc744 \ub9cc\ub4e4\uc5c8\ub2e4. Python\uc5d0\uc120 List\uac00 stack \uae30\ub2a5\ub3c4 \uc9c0\uc6d0\ud55c\ub2e4. <\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers\" data-code-block-pro-font-family=\"Code-Pro-Roboto-Mono.ttf\" style=\"font-size:clamp(14px, .875rem, 21px);font-family:Code-Pro-Roboto-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#adbac7;--cbp-line-number-width:calc(2 * 0.6 * .875rem);line-height:clamp(20px, 1.25rem, 30px);--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#22272e\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"54\" height=\"14\" viewBox=\"0 0 54 14\"><g fill=\"none\" fill-rule=\"evenodd\" transform=\"translate(1 1)\"><circle cx=\"6\" cy=\"6\" r=\"6\" fill=\"#FF5F56\" stroke=\"#E0443E\" stroke-width=\".5\"><\/circle><circle cx=\"26\" cy=\"6\" r=\"6\" fill=\"#FFBD2E\" stroke=\"#DEA123\" stroke-width=\".5\"><\/circle><circle cx=\"46\" cy=\"6\" r=\"6\" fill=\"#27C93F\" stroke=\"#1AAB29\" stroke-width=\".5\"><\/circle><\/g><\/svg><\/span><span role=\"button\" tabindex=\"0\" style=\"color:#adbac7;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><pre class=\"code-block-pro-copy-button-pre\" aria-hidden=\"true\"><textarea class=\"code-block-pro-copy-button-textarea\" tabindex=\"-1\" aria-hidden=\"true\" readonly>import random\nfrom typing import List\nfrom command.ICommand import ICommand\nfrom command.commandstack import CommandStack\nfrom command.dummyplayer import DummyMusicPlayer\n\n\nclass ShuffleCommand(ICommand):\n    def __init__(self, receiver: DummyMusicPlayer, undo_stack: CommandStack):\n        self._receiver = receiver\n        self._undo_stack = undo_stack\n        self._backup_list: List&#91;str&#93; = None\n\n    def execute(self):\n        # self._backup_list = self._receiver.shuffle()\n        playlist = self._receiver.playlist\n        self._backup_list = playlist&#91;:&#93;\n        random.shuffle(playlist)\n        cmd = ShuffleCommand(self._receiver, self._undo_stack)\n        cmd._backup_list = self._backup_list\n        self._undo_stack.push_cmd(cmd)\n\n    def undo(self):\n        print(\"shuffle undo\")\n        if self._backup_list is not None:\n            self._receiver.playlist = self._backup_list\n\n\nclass AppendCommand(ICommand):\n    def __init__(self, receiver: DummyMusicPlayer, undo_stack: CommandStack):\n        self._receiver = receiver\n        self._undo_stack = undo_stack\n        self._idx = -1\n\n    def execute(self):\n        song = _DummyFileOpenDlg.call_file_open_dlg()\n        self._idx = self._receiver.append(song)\n        cmd = AppendCommand(self._receiver, self._undo_stack)\n        cmd._idx = self._idx\n        self._undo_stack.push_cmd(cmd)\n\n    def undo(self):\n        print(\"append undo\")\n        if self._idx != -1:\n            self._receiver.delete(self._idx)\n\n\nclass DeleteCommand(ICommand):\n    def __init__(self, receiver: DummyMusicPlayer, undo_stack: CommandStack):\n        self._receiver = receiver\n        self._undo_stack = undo_stack\n        self._song: str = \"\"\n        self._idx: int = -1\n\n    def execute(self):\n        self._idx = self._receiver.selected\n        self._song = self._receiver.delete(self._idx)\n        cmd = DeleteCommand(self._receiver, self._undo_stack)\n        cmd._song = self._song\n        cmd._idx = self._idx\n        self._undo_stack.push_cmd(cmd)\n\n    def undo(self):\n        if self._idx != -1:\n            self._receiver.insert(self._idx, self._song)\n\n\n# only for test. emulate FileOpenDialog\nclass _DummyFileOpenDlg:\n    _test_songs = &#91;\"song1\", \"song2\", \"song3\", \"song4\", \"song5\"&#93;\n    _file_open_idx = 0\n\n    @classmethod\n    def call_file_open_dlg(cls) -> str:\n        song = cls._test_songs&#91;cls._file_open_idx&#93;\n        cls._file_open_idx += 1\n        if cls._file_open_idx >= len(cls._test_songs):\n            cls._file_open_idx = 0\n        return song\n\n<\/textarea><\/pre><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki github-dark-dimmed\" style=\"background-color: #22272e\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #F47067\">import<\/span><span style=\"color: #ADBAC7\"> random<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F47067\">from<\/span><span style=\"color: #ADBAC7\"> typing <\/span><span style=\"color: #F47067\">import<\/span><span style=\"color: #ADBAC7\"> List<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F47067\">from<\/span><span style=\"color: #ADBAC7\"> command.ICommand <\/span><span style=\"color: #F47067\">import<\/span><span style=\"color: #ADBAC7\"> ICommand<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F47067\">from<\/span><span style=\"color: #ADBAC7\"> command.commandstack <\/span><span style=\"color: #F47067\">import<\/span><span style=\"color: #ADBAC7\"> CommandStack<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F47067\">from<\/span><span style=\"color: #ADBAC7\"> command.dummyplayer <\/span><span style=\"color: #F47067\">import<\/span><span style=\"color: #ADBAC7\"> DummyMusicPlayer<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #F47067\">class<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #F69D50\">ShuffleCommand<\/span><span style=\"color: #ADBAC7\">(<\/span><span style=\"color: #6CB6FF\">ICommand<\/span><span style=\"color: #ADBAC7\">):<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">    <\/span><span style=\"color: #F47067\">def<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #6CB6FF\">__init__<\/span><span style=\"color: #ADBAC7\">(self, receiver: DummyMusicPlayer, undo_stack: CommandStack):<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">        <\/span><span style=\"color: #6CB6FF\">self<\/span><span style=\"color: #ADBAC7\">._receiver <\/span><span style=\"color: #F47067\">=<\/span><span style=\"color: #ADBAC7\"> receiver<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">        <\/span><span style=\"color: #6CB6FF\">self<\/span><span style=\"color: #ADBAC7\">._undo_stack <\/span><span style=\"color: #F47067\">=<\/span><span style=\"color: #ADBAC7\"> undo_stack<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">        <\/span><span style=\"color: #6CB6FF\">self<\/span><span style=\"color: #ADBAC7\">._backup_list: List&#91;<\/span><span style=\"color: #6CB6FF\">str<\/span><span style=\"color: #ADBAC7\">&#93; <\/span><span style=\"color: #F47067\">=<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #6CB6FF\">None<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">    <\/span><span style=\"color: #F47067\">def<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #DCBDFB\">execute<\/span><span style=\"color: #ADBAC7\">(self):<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">        <\/span><span style=\"color: #768390\"># self._backup_list = self._receiver.shuffle()<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">        playlist <\/span><span style=\"color: #F47067\">=<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #6CB6FF\">self<\/span><span style=\"color: #ADBAC7\">._receiver.playlist<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">        <\/span><span style=\"color: #6CB6FF\">self<\/span><span style=\"color: #ADBAC7\">._backup_list <\/span><span style=\"color: #F47067\">=<\/span><span style=\"color: #ADBAC7\"> playlist&#91;:&#93;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">        random.shuffle(playlist)<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">        cmd <\/span><span style=\"color: #F47067\">=<\/span><span style=\"color: #ADBAC7\"> ShuffleCommand(<\/span><span style=\"color: #6CB6FF\">self<\/span><span style=\"color: #ADBAC7\">._receiver, <\/span><span style=\"color: #6CB6FF\">self<\/span><span style=\"color: #ADBAC7\">._undo_stack)<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">        cmd._backup_list <\/span><span style=\"color: #F47067\">=<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #6CB6FF\">self<\/span><span style=\"color: #ADBAC7\">._backup_list<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">        <\/span><span style=\"color: #6CB6FF\">self<\/span><span style=\"color: #ADBAC7\">._undo_stack.push_cmd(cmd)<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">    <\/span><span style=\"color: #F47067\">def<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #DCBDFB\">undo<\/span><span style=\"color: #ADBAC7\">(self):<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">        <\/span><span style=\"color: #6CB6FF\">print<\/span><span style=\"color: #ADBAC7\">(<\/span><span style=\"color: #96D0FF\">&quot;shuffle undo&quot;<\/span><span style=\"color: #ADBAC7\">)<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">        <\/span><span style=\"color: #F47067\">if<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #6CB6FF\">self<\/span><span style=\"color: #ADBAC7\">._backup_list <\/span><span style=\"color: #F47067\">is<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #F47067\">not<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #6CB6FF\">None<\/span><span style=\"color: #ADBAC7\">:<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">            <\/span><span style=\"color: #6CB6FF\">self<\/span><span style=\"color: #ADBAC7\">._receiver.playlist <\/span><span style=\"color: #F47067\">=<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #6CB6FF\">self<\/span><span style=\"color: #ADBAC7\">._backup_list<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #F47067\">class<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #F69D50\">AppendCommand<\/span><span style=\"color: #ADBAC7\">(<\/span><span style=\"color: #6CB6FF\">ICommand<\/span><span style=\"color: #ADBAC7\">):<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">    <\/span><span style=\"color: #F47067\">def<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #6CB6FF\">__init__<\/span><span style=\"color: #ADBAC7\">(self, receiver: DummyMusicPlayer, undo_stack: CommandStack):<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">        <\/span><span style=\"color: #6CB6FF\">self<\/span><span style=\"color: #ADBAC7\">._receiver <\/span><span style=\"color: #F47067\">=<\/span><span style=\"color: #ADBAC7\"> receiver<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">        <\/span><span style=\"color: #6CB6FF\">self<\/span><span style=\"color: #ADBAC7\">._undo_stack <\/span><span style=\"color: #F47067\">=<\/span><span style=\"color: #ADBAC7\"> undo_stack<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">        <\/span><span style=\"color: #6CB6FF\">self<\/span><span style=\"color: #ADBAC7\">._idx <\/span><span style=\"color: #F47067\">=<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #F47067\">-<\/span><span style=\"color: #6CB6FF\">1<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">    <\/span><span style=\"color: #F47067\">def<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #DCBDFB\">execute<\/span><span style=\"color: #ADBAC7\">(self):<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">        song <\/span><span style=\"color: #F47067\">=<\/span><span style=\"color: #ADBAC7\"> _DummyFileOpenDlg.call_file_open_dlg()<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">        <\/span><span style=\"color: #6CB6FF\">self<\/span><span style=\"color: #ADBAC7\">._idx <\/span><span style=\"color: #F47067\">=<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #6CB6FF\">self<\/span><span style=\"color: #ADBAC7\">._receiver.append(song)<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">        cmd <\/span><span style=\"color: #F47067\">=<\/span><span style=\"color: #ADBAC7\"> AppendCommand(<\/span><span style=\"color: #6CB6FF\">self<\/span><span style=\"color: #ADBAC7\">._receiver, <\/span><span style=\"color: #6CB6FF\">self<\/span><span style=\"color: #ADBAC7\">._undo_stack)<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">        cmd._idx <\/span><span style=\"color: #F47067\">=<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #6CB6FF\">self<\/span><span style=\"color: #ADBAC7\">._idx<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">        <\/span><span style=\"color: #6CB6FF\">self<\/span><span style=\"color: #ADBAC7\">._undo_stack.push_cmd(cmd)<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">    <\/span><span style=\"color: #F47067\">def<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #DCBDFB\">undo<\/span><span style=\"color: #ADBAC7\">(self):<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">        <\/span><span style=\"color: #6CB6FF\">print<\/span><span style=\"color: #ADBAC7\">(<\/span><span style=\"color: #96D0FF\">&quot;append undo&quot;<\/span><span style=\"color: #ADBAC7\">)<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">        <\/span><span style=\"color: #F47067\">if<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #6CB6FF\">self<\/span><span style=\"color: #ADBAC7\">._idx <\/span><span style=\"color: #F47067\">!=<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #F47067\">-<\/span><span style=\"color: #6CB6FF\">1<\/span><span style=\"color: #ADBAC7\">:<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">            <\/span><span style=\"color: #6CB6FF\">self<\/span><span style=\"color: #ADBAC7\">._receiver.delete(<\/span><span style=\"color: #6CB6FF\">self<\/span><span style=\"color: #ADBAC7\">._idx)<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #F47067\">class<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #F69D50\">DeleteCommand<\/span><span style=\"color: #ADBAC7\">(<\/span><span style=\"color: #6CB6FF\">ICommand<\/span><span style=\"color: #ADBAC7\">):<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">    <\/span><span style=\"color: #F47067\">def<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #6CB6FF\">__init__<\/span><span style=\"color: #ADBAC7\">(self, receiver: DummyMusicPlayer, undo_stack: CommandStack):<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">        <\/span><span style=\"color: #6CB6FF\">self<\/span><span style=\"color: #ADBAC7\">._receiver <\/span><span style=\"color: #F47067\">=<\/span><span style=\"color: #ADBAC7\"> receiver<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">        <\/span><span style=\"color: #6CB6FF\">self<\/span><span style=\"color: #ADBAC7\">._undo_stack <\/span><span style=\"color: #F47067\">=<\/span><span style=\"color: #ADBAC7\"> undo_stack<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">        <\/span><span style=\"color: #6CB6FF\">self<\/span><span style=\"color: #ADBAC7\">._song: <\/span><span style=\"color: #6CB6FF\">str<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #F47067\">=<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #96D0FF\">&quot;&quot;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">        <\/span><span style=\"color: #6CB6FF\">self<\/span><span style=\"color: #ADBAC7\">._idx: <\/span><span style=\"color: #6CB6FF\">int<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #F47067\">=<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #F47067\">-<\/span><span style=\"color: #6CB6FF\">1<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">    <\/span><span style=\"color: #F47067\">def<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #DCBDFB\">execute<\/span><span style=\"color: #ADBAC7\">(self):<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">        <\/span><span style=\"color: #6CB6FF\">self<\/span><span style=\"color: #ADBAC7\">._idx <\/span><span style=\"color: #F47067\">=<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #6CB6FF\">self<\/span><span style=\"color: #ADBAC7\">._receiver.selected<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">        <\/span><span style=\"color: #6CB6FF\">self<\/span><span style=\"color: #ADBAC7\">._song <\/span><span style=\"color: #F47067\">=<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #6CB6FF\">self<\/span><span style=\"color: #ADBAC7\">._receiver.delete(<\/span><span style=\"color: #6CB6FF\">self<\/span><span style=\"color: #ADBAC7\">._idx)<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">        cmd <\/span><span style=\"color: #F47067\">=<\/span><span style=\"color: #ADBAC7\"> DeleteCommand(<\/span><span style=\"color: #6CB6FF\">self<\/span><span style=\"color: #ADBAC7\">._receiver, <\/span><span style=\"color: #6CB6FF\">self<\/span><span style=\"color: #ADBAC7\">._undo_stack)<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">        cmd._song <\/span><span style=\"color: #F47067\">=<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #6CB6FF\">self<\/span><span style=\"color: #ADBAC7\">._song<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">        cmd._idx <\/span><span style=\"color: #F47067\">=<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #6CB6FF\">self<\/span><span style=\"color: #ADBAC7\">._idx<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">        <\/span><span style=\"color: #6CB6FF\">self<\/span><span style=\"color: #ADBAC7\">._undo_stack.push_cmd(cmd)<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">    <\/span><span style=\"color: #F47067\">def<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #DCBDFB\">undo<\/span><span style=\"color: #ADBAC7\">(self):<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">        <\/span><span style=\"color: #F47067\">if<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #6CB6FF\">self<\/span><span style=\"color: #ADBAC7\">._idx <\/span><span style=\"color: #F47067\">!=<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #F47067\">-<\/span><span style=\"color: #6CB6FF\">1<\/span><span style=\"color: #ADBAC7\">:<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">            <\/span><span style=\"color: #6CB6FF\">self<\/span><span style=\"color: #ADBAC7\">._receiver.insert(<\/span><span style=\"color: #6CB6FF\">self<\/span><span style=\"color: #ADBAC7\">._idx, <\/span><span style=\"color: #6CB6FF\">self<\/span><span style=\"color: #ADBAC7\">._song)<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #768390\"># only for test. emulate FileOpenDialog<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F47067\">class<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #F69D50\">_DummyFileOpenDlg<\/span><span style=\"color: #ADBAC7\">:<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">    _test_songs <\/span><span style=\"color: #F47067\">=<\/span><span style=\"color: #ADBAC7\"> &#91;<\/span><span style=\"color: #96D0FF\">&quot;song1&quot;<\/span><span style=\"color: #ADBAC7\">, <\/span><span style=\"color: #96D0FF\">&quot;song2&quot;<\/span><span style=\"color: #ADBAC7\">, <\/span><span style=\"color: #96D0FF\">&quot;song3&quot;<\/span><span style=\"color: #ADBAC7\">, <\/span><span style=\"color: #96D0FF\">&quot;song4&quot;<\/span><span style=\"color: #ADBAC7\">, <\/span><span style=\"color: #96D0FF\">&quot;song5&quot;<\/span><span style=\"color: #ADBAC7\">&#93;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">    _file_open_idx <\/span><span style=\"color: #F47067\">=<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #6CB6FF\">0<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">    <\/span><span style=\"color: #DCBDFB\">@<\/span><span style=\"color: #6CB6FF\">classmethod<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">    <\/span><span style=\"color: #F47067\">def<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #DCBDFB\">call_file_open_dlg<\/span><span style=\"color: #ADBAC7\">(cls) -&gt; <\/span><span style=\"color: #6CB6FF\">str<\/span><span style=\"color: #ADBAC7\">:<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">        song <\/span><span style=\"color: #F47067\">=<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #6CB6FF\">cls<\/span><span style=\"color: #ADBAC7\">._test_songs&#91;<\/span><span style=\"color: #6CB6FF\">cls<\/span><span style=\"color: #ADBAC7\">._file_open_idx&#93;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">        <\/span><span style=\"color: #6CB6FF\">cls<\/span><span style=\"color: #ADBAC7\">._file_open_idx <\/span><span style=\"color: #F47067\">+=<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #6CB6FF\">1<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">        <\/span><span style=\"color: #F47067\">if<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #6CB6FF\">cls<\/span><span style=\"color: #ADBAC7\">._file_open_idx <\/span><span style=\"color: #F47067\">&gt;=<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #6CB6FF\">len<\/span><span style=\"color: #ADBAC7\">(<\/span><span style=\"color: #6CB6FF\">cls<\/span><span style=\"color: #ADBAC7\">._test_songs):<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">            <\/span><span style=\"color: #6CB6FF\">cls<\/span><span style=\"color: #ADBAC7\">._file_open_idx <\/span><span style=\"color: #F47067\">=<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #6CB6FF\">0<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">        <\/span><span style=\"color: #F47067\">return<\/span><span style=\"color: #ADBAC7\"> song<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><\/span><\/code><\/pre><\/div>\n\n\n\n<p>\uac01 \ucee4\ub9e8\ub4dc\ub4e4\uc744 \uad6c\ud604\ud588\ub2e4. \uc2a4\ud0dd\uc5d0 \ub123\uc744 \ucee4\ub9e8\ub4dc\ub97c \ucc98\uc74c\uc5d4 copy.deepcopy()\ub97c \uc0ac\uc6a9\ud588\uc5c8\ub294\ub370, \uc774\uacbd\uc6b0 \uc0dd\uc131\uc790\ub85c \ub118\uaca8\ubc1b\uc740 receiver\uc640 stack\ub3c4 deep copy\ub418\uc5b4 \ubcc4\ub3c4\uc758 \uc778\uc2a4\ud134\uc2a4\ub85c \uc0dd\uc131\ub41c\ub2e4. \uc55e\uc5d0\uc11c\ub3c4 \uc598\uae30\ud588\uc9c0\ub9cc, \ucee4\uc2a4\ud140 clone \ud568\uc218\ub97c \uc791\uc131\ud558\ub294\uac8c \uac00\uc7a5 \uae54\ub054\ud560 \uac83\uc774\ub2e4. \uc5ec\uae30\uc120 \uc548\ud588\uc9c0\ub9cc \ud83d\ude00<\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers\" data-code-block-pro-font-family=\"Code-Pro-Roboto-Mono.ttf\" style=\"font-size:clamp(14px, .875rem, 21px);font-family:Code-Pro-Roboto-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#adbac7;--cbp-line-number-width:calc(2 * 0.6 * .875rem);line-height:clamp(20px, 1.25rem, 30px);--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#22272e\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"54\" height=\"14\" viewBox=\"0 0 54 14\"><g fill=\"none\" fill-rule=\"evenodd\" transform=\"translate(1 1)\"><circle cx=\"6\" cy=\"6\" r=\"6\" fill=\"#FF5F56\" stroke=\"#E0443E\" stroke-width=\".5\"><\/circle><circle cx=\"26\" cy=\"6\" r=\"6\" fill=\"#FFBD2E\" stroke=\"#DEA123\" stroke-width=\".5\"><\/circle><circle cx=\"46\" cy=\"6\" r=\"6\" fill=\"#27C93F\" stroke=\"#1AAB29\" stroke-width=\".5\"><\/circle><\/g><\/svg><\/span><span role=\"button\" tabindex=\"0\" style=\"color:#adbac7;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><pre class=\"code-block-pro-copy-button-pre\" aria-hidden=\"true\"><textarea class=\"code-block-pro-copy-button-textarea\" tabindex=\"-1\" aria-hidden=\"true\" readonly>from command.commands import ICommand\n\n\nclass DummyButton:\n    def __init__(self, name: str):\n        self.name: str = name\n        self._command: ICommand = None\n\n    def assign_command(self, cmd: ICommand):\n        self._command = cmd\n\n    def pressed(self):\n        if self._command is not None:\n            self._command.execute()\n<\/textarea><\/pre><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki github-dark-dimmed\" style=\"background-color: #22272e\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #F47067\">from<\/span><span style=\"color: #ADBAC7\"> command.commands <\/span><span style=\"color: #F47067\">import<\/span><span style=\"color: #ADBAC7\"> ICommand<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #F47067\">class<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #F69D50\">DummyButton<\/span><span style=\"color: #ADBAC7\">:<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">    <\/span><span style=\"color: #F47067\">def<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #6CB6FF\">__init__<\/span><span style=\"color: #ADBAC7\">(self, name: <\/span><span style=\"color: #6CB6FF\">str<\/span><span style=\"color: #ADBAC7\">):<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">        <\/span><span style=\"color: #6CB6FF\">self<\/span><span style=\"color: #ADBAC7\">.name: <\/span><span style=\"color: #6CB6FF\">str<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #F47067\">=<\/span><span style=\"color: #ADBAC7\"> name<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">        <\/span><span style=\"color: #6CB6FF\">self<\/span><span style=\"color: #ADBAC7\">._command: ICommand <\/span><span style=\"color: #F47067\">=<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #6CB6FF\">None<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">    <\/span><span style=\"color: #F47067\">def<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #DCBDFB\">assign_command<\/span><span style=\"color: #ADBAC7\">(self, cmd: ICommand):<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">        <\/span><span style=\"color: #6CB6FF\">self<\/span><span style=\"color: #ADBAC7\">._command <\/span><span style=\"color: #F47067\">=<\/span><span style=\"color: #ADBAC7\"> cmd<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">    <\/span><span style=\"color: #F47067\">def<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #DCBDFB\">pressed<\/span><span style=\"color: #ADBAC7\">(self):<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">        <\/span><span style=\"color: #F47067\">if<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #6CB6FF\">self<\/span><span style=\"color: #ADBAC7\">._command <\/span><span style=\"color: #F47067\">is<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #F47067\">not<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #6CB6FF\">None<\/span><span style=\"color: #ADBAC7\">:<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">            <\/span><span style=\"color: #6CB6FF\">self<\/span><span style=\"color: #ADBAC7\">._command.execute()<\/span><\/span>\n<span class=\"line\"><\/span><\/code><\/pre><\/div>\n\n\n\n<p>\uac04\ub2e8\ud55c DummyButton\uc758 \uad6c\ud604.<\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers\" data-code-block-pro-font-family=\"Code-Pro-Roboto-Mono.ttf\" style=\"font-size:clamp(14px, .875rem, 21px);font-family:Code-Pro-Roboto-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#adbac7;--cbp-line-number-width:calc(2 * 0.6 * .875rem);line-height:clamp(20px, 1.25rem, 30px);--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#22272e\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"54\" height=\"14\" viewBox=\"0 0 54 14\"><g fill=\"none\" fill-rule=\"evenodd\" transform=\"translate(1 1)\"><circle cx=\"6\" cy=\"6\" r=\"6\" fill=\"#FF5F56\" stroke=\"#E0443E\" stroke-width=\".5\"><\/circle><circle cx=\"26\" cy=\"6\" r=\"6\" fill=\"#FFBD2E\" stroke=\"#DEA123\" stroke-width=\".5\"><\/circle><circle cx=\"46\" cy=\"6\" r=\"6\" fill=\"#27C93F\" stroke=\"#1AAB29\" stroke-width=\".5\"><\/circle><\/g><\/svg><\/span><span role=\"button\" tabindex=\"0\" style=\"color:#adbac7;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><pre class=\"code-block-pro-copy-button-pre\" aria-hidden=\"true\"><textarea class=\"code-block-pro-copy-button-textarea\" tabindex=\"-1\" aria-hidden=\"true\" readonly>from command.button import DummyButton\nfrom command.commands import AppendCommand, DeleteCommand, ShuffleCommand\nfrom command.commandstack import CommandStack\nfrom command.dummyplayer import DummyMusicPlayer\n\n\ndef main():\n    music_player = DummyMusicPlayer()\n    undo_stack = CommandStack()\n\n    addCmd = AppendCommand(music_player, undo_stack)\n    delCmd = DeleteCommand(music_player, undo_stack)\n    shuffleCmd = ShuffleCommand(music_player, undo_stack)\n\n    add_button = DummyButton(\"ADD\")\n    add_button.assign_command(addCmd)\n    delete_button = DummyButton(\"DELETE\")\n    delete_button.assign_command(delCmd)\n    shuffle_button = DummyButton(\"SHUFFLE\")\n    shuffle_button.assign_command(shuffleCmd)\n\n    add_button.pressed()\n    add_button.pressed()\n    add_button.pressed()\n    add_button.pressed()\n    add_button.pressed()\n    print(\"add test\")\n    print(music_player.playlist)\n\n    shuffle_button.pressed()\n    print(\"shuffle test\")\n    print(music_player.playlist)\n\n    music_player.selected = 3\n    delete_button.pressed()\n    music_player.selected = 0\n    delete_button.pressed()\n    print(\"delete test\")\n    print(music_player.playlist)\n\n    print(\"undo test\")\n    undo_stack.undo()\n    print(music_player.playlist)\n    undo_stack.undo()\n    print(music_player.playlist)\n    undo_stack.undo()\n    print(music_player.playlist)\n    undo_stack.undo()\n    print(music_player.playlist)\n    undo_stack.undo()\n    print(music_player.playlist)\n\n\nif __name__ == \"__main__\":\n    main()\n\n<\/textarea><\/pre><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki github-dark-dimmed\" style=\"background-color: #22272e\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #F47067\">from<\/span><span style=\"color: #ADBAC7\"> command.button <\/span><span style=\"color: #F47067\">import<\/span><span style=\"color: #ADBAC7\"> DummyButton<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F47067\">from<\/span><span style=\"color: #ADBAC7\"> command.commands <\/span><span style=\"color: #F47067\">import<\/span><span style=\"color: #ADBAC7\"> AppendCommand, DeleteCommand, ShuffleCommand<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F47067\">from<\/span><span style=\"color: #ADBAC7\"> command.commandstack <\/span><span style=\"color: #F47067\">import<\/span><span style=\"color: #ADBAC7\"> CommandStack<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F47067\">from<\/span><span style=\"color: #ADBAC7\"> command.dummyplayer <\/span><span style=\"color: #F47067\">import<\/span><span style=\"color: #ADBAC7\"> DummyMusicPlayer<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #F47067\">def<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #DCBDFB\">main<\/span><span style=\"color: #ADBAC7\">():<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">    music_player <\/span><span style=\"color: #F47067\">=<\/span><span style=\"color: #ADBAC7\"> DummyMusicPlayer()<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">    undo_stack <\/span><span style=\"color: #F47067\">=<\/span><span style=\"color: #ADBAC7\"> CommandStack()<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">    addCmd <\/span><span style=\"color: #F47067\">=<\/span><span style=\"color: #ADBAC7\"> AppendCommand(music_player, undo_stack)<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">    delCmd <\/span><span style=\"color: #F47067\">=<\/span><span style=\"color: #ADBAC7\"> DeleteCommand(music_player, undo_stack)<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">    shuffleCmd <\/span><span style=\"color: #F47067\">=<\/span><span style=\"color: #ADBAC7\"> ShuffleCommand(music_player, undo_stack)<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">    add_button <\/span><span style=\"color: #F47067\">=<\/span><span style=\"color: #ADBAC7\"> DummyButton(<\/span><span style=\"color: #96D0FF\">&quot;ADD&quot;<\/span><span style=\"color: #ADBAC7\">)<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">    add_button.assign_command(addCmd)<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">    delete_button <\/span><span style=\"color: #F47067\">=<\/span><span style=\"color: #ADBAC7\"> DummyButton(<\/span><span style=\"color: #96D0FF\">&quot;DELETE&quot;<\/span><span style=\"color: #ADBAC7\">)<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">    delete_button.assign_command(delCmd)<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">    shuffle_button <\/span><span style=\"color: #F47067\">=<\/span><span style=\"color: #ADBAC7\"> DummyButton(<\/span><span style=\"color: #96D0FF\">&quot;SHUFFLE&quot;<\/span><span style=\"color: #ADBAC7\">)<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">    shuffle_button.assign_command(shuffleCmd)<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">    add_button.pressed()<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">    add_button.pressed()<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">    add_button.pressed()<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">    add_button.pressed()<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">    add_button.pressed()<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">    <\/span><span style=\"color: #6CB6FF\">print<\/span><span style=\"color: #ADBAC7\">(<\/span><span style=\"color: #96D0FF\">&quot;add test&quot;<\/span><span style=\"color: #ADBAC7\">)<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">    <\/span><span style=\"color: #6CB6FF\">print<\/span><span style=\"color: #ADBAC7\">(music_player.playlist)<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">    shuffle_button.pressed()<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">    <\/span><span style=\"color: #6CB6FF\">print<\/span><span style=\"color: #ADBAC7\">(<\/span><span style=\"color: #96D0FF\">&quot;shuffle test&quot;<\/span><span style=\"color: #ADBAC7\">)<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">    <\/span><span style=\"color: #6CB6FF\">print<\/span><span style=\"color: #ADBAC7\">(music_player.playlist)<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">    music_player.selected <\/span><span style=\"color: #F47067\">=<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #6CB6FF\">3<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">    delete_button.pressed()<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">    music_player.selected <\/span><span style=\"color: #F47067\">=<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #6CB6FF\">0<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">    delete_button.pressed()<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">    <\/span><span style=\"color: #6CB6FF\">print<\/span><span style=\"color: #ADBAC7\">(<\/span><span style=\"color: #96D0FF\">&quot;delete test&quot;<\/span><span style=\"color: #ADBAC7\">)<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">    <\/span><span style=\"color: #6CB6FF\">print<\/span><span style=\"color: #ADBAC7\">(music_player.playlist)<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">    <\/span><span style=\"color: #6CB6FF\">print<\/span><span style=\"color: #ADBAC7\">(<\/span><span style=\"color: #96D0FF\">&quot;undo test&quot;<\/span><span style=\"color: #ADBAC7\">)<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">    undo_stack.undo()<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">    <\/span><span style=\"color: #6CB6FF\">print<\/span><span style=\"color: #ADBAC7\">(music_player.playlist)<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">    undo_stack.undo()<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">    <\/span><span style=\"color: #6CB6FF\">print<\/span><span style=\"color: #ADBAC7\">(music_player.playlist)<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">    undo_stack.undo()<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">    <\/span><span style=\"color: #6CB6FF\">print<\/span><span style=\"color: #ADBAC7\">(music_player.playlist)<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">    undo_stack.undo()<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">    <\/span><span style=\"color: #6CB6FF\">print<\/span><span style=\"color: #ADBAC7\">(music_player.playlist)<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">    undo_stack.undo()<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">    <\/span><span style=\"color: #6CB6FF\">print<\/span><span style=\"color: #ADBAC7\">(music_player.playlist)<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #F47067\">if<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #6CB6FF\">__name__<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #F47067\">==<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #96D0FF\">&quot;__main__&quot;<\/span><span style=\"color: #ADBAC7\">:<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">    main()<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><\/span><\/code><\/pre><\/div>\n\n\n\n<p>\ud14c\uc2a4\ud2b8 \ud074\ub77c\uc774\uc5b8\ud2b8 \ucf54\ub4dc\ub294 \uc55e\uc5d0\uc11c\uc640 \ub3d9\uc77c\ud558\ub2e4. \ub2e4\uc74c \uacb0\uacfc\ucc98\ub7fc \uc798 \uc790\ub3d9\ud558\ub294\uac78 \uc54c \uc218 \uc788\ub2e4.<\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers\" data-code-block-pro-font-family=\"Code-Pro-Roboto-Mono.ttf\" style=\"font-size:clamp(14px, .875rem, 21px);font-family:Code-Pro-Roboto-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#adbac7;--cbp-line-number-width:calc(2 * 0.6 * .875rem);line-height:clamp(20px, 1.25rem, 30px);--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#22272e\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"54\" height=\"14\" viewBox=\"0 0 54 14\"><g fill=\"none\" fill-rule=\"evenodd\" transform=\"translate(1 1)\"><circle cx=\"6\" cy=\"6\" r=\"6\" fill=\"#FF5F56\" stroke=\"#E0443E\" stroke-width=\".5\"><\/circle><circle cx=\"26\" cy=\"6\" r=\"6\" fill=\"#FFBD2E\" stroke=\"#DEA123\" stroke-width=\".5\"><\/circle><circle cx=\"46\" cy=\"6\" r=\"6\" fill=\"#27C93F\" stroke=\"#1AAB29\" stroke-width=\".5\"><\/circle><\/g><\/svg><\/span><span role=\"button\" tabindex=\"0\" style=\"color:#adbac7;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><pre class=\"code-block-pro-copy-button-pre\" aria-hidden=\"true\"><textarea class=\"code-block-pro-copy-button-textarea\" tabindex=\"-1\" aria-hidden=\"true\" readonly>add test\n&#91;'song1', 'song2', 'song3', 'song4', 'song5'&#93;\nshuffle test\n&#91;'song3', 'song1', 'song5', 'song2', 'song4'&#93;\ndelete test\n&#91;'song1', 'song5', 'song4'&#93;\nundo test\n&#91;'song3', 'song1', 'song5', 'song4'&#93;\n&#91;'song3', 'song1', 'song5', 'song2', 'song4'&#93;\nshuffle undo\n&#91;'song1', 'song2', 'song3', 'song4', 'song5'&#93;\nappend undo\n&#91;'song1', 'song2', 'song3', 'song4'&#93;\nappend undo\n&#91;'song1', 'song2', 'song3'&#93;<\/textarea><\/pre><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki github-dark-dimmed\" style=\"background-color: #22272e\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #ADBAC7\">add test<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">&#91;<\/span><span style=\"color: #96D0FF\">&#39;song1&#39;<\/span><span style=\"color: #ADBAC7\">, <\/span><span style=\"color: #96D0FF\">&#39;song2&#39;<\/span><span style=\"color: #ADBAC7\">, <\/span><span style=\"color: #96D0FF\">&#39;song3&#39;<\/span><span style=\"color: #ADBAC7\">, <\/span><span style=\"color: #96D0FF\">&#39;song4&#39;<\/span><span style=\"color: #ADBAC7\">, <\/span><span style=\"color: #96D0FF\">&#39;song5&#39;<\/span><span style=\"color: #ADBAC7\">&#93;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">shuffle test<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">&#91;<\/span><span style=\"color: #96D0FF\">&#39;song3&#39;<\/span><span style=\"color: #ADBAC7\">, <\/span><span style=\"color: #96D0FF\">&#39;song1&#39;<\/span><span style=\"color: #ADBAC7\">, <\/span><span style=\"color: #96D0FF\">&#39;song5&#39;<\/span><span style=\"color: #ADBAC7\">, <\/span><span style=\"color: #96D0FF\">&#39;song2&#39;<\/span><span style=\"color: #ADBAC7\">, <\/span><span style=\"color: #96D0FF\">&#39;song4&#39;<\/span><span style=\"color: #ADBAC7\">&#93;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">delete test<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">&#91;<\/span><span style=\"color: #96D0FF\">&#39;song1&#39;<\/span><span style=\"color: #ADBAC7\">, <\/span><span style=\"color: #96D0FF\">&#39;song5&#39;<\/span><span style=\"color: #ADBAC7\">, <\/span><span style=\"color: #96D0FF\">&#39;song4&#39;<\/span><span style=\"color: #ADBAC7\">&#93;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">undo test<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">&#91;<\/span><span style=\"color: #96D0FF\">&#39;song3&#39;<\/span><span style=\"color: #ADBAC7\">, <\/span><span style=\"color: #96D0FF\">&#39;song1&#39;<\/span><span style=\"color: #ADBAC7\">, <\/span><span style=\"color: #96D0FF\">&#39;song5&#39;<\/span><span style=\"color: #ADBAC7\">, <\/span><span style=\"color: #96D0FF\">&#39;song4&#39;<\/span><span style=\"color: #ADBAC7\">&#93;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">&#91;<\/span><span style=\"color: #96D0FF\">&#39;song3&#39;<\/span><span style=\"color: #ADBAC7\">, <\/span><span style=\"color: #96D0FF\">&#39;song1&#39;<\/span><span style=\"color: #ADBAC7\">, <\/span><span style=\"color: #96D0FF\">&#39;song5&#39;<\/span><span style=\"color: #ADBAC7\">, <\/span><span style=\"color: #96D0FF\">&#39;song2&#39;<\/span><span style=\"color: #ADBAC7\">, <\/span><span style=\"color: #96D0FF\">&#39;song4&#39;<\/span><span style=\"color: #ADBAC7\">&#93;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">shuffle undo<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">&#91;<\/span><span style=\"color: #96D0FF\">&#39;song1&#39;<\/span><span style=\"color: #ADBAC7\">, <\/span><span style=\"color: #96D0FF\">&#39;song2&#39;<\/span><span style=\"color: #ADBAC7\">, <\/span><span style=\"color: #96D0FF\">&#39;song3&#39;<\/span><span style=\"color: #ADBAC7\">, <\/span><span style=\"color: #96D0FF\">&#39;song4&#39;<\/span><span style=\"color: #ADBAC7\">, <\/span><span style=\"color: #96D0FF\">&#39;song5&#39;<\/span><span style=\"color: #ADBAC7\">&#93;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">append undo<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">&#91;<\/span><span style=\"color: #96D0FF\">&#39;song1&#39;<\/span><span style=\"color: #ADBAC7\">, <\/span><span style=\"color: #96D0FF\">&#39;song2&#39;<\/span><span style=\"color: #ADBAC7\">, <\/span><span style=\"color: #96D0FF\">&#39;song3&#39;<\/span><span style=\"color: #ADBAC7\">, <\/span><span style=\"color: #96D0FF\">&#39;song4&#39;<\/span><span style=\"color: #ADBAC7\">&#93;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">append undo<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">&#91;<\/span><span style=\"color: #96D0FF\">&#39;song1&#39;<\/span><span style=\"color: #ADBAC7\">, <\/span><span style=\"color: #96D0FF\">&#39;song2&#39;<\/span><span style=\"color: #ADBAC7\">, <\/span><span style=\"color: #96D0FF\">&#39;song3&#39;<\/span><span style=\"color: #ADBAC7\">&#93;<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<hr class=\"wp-block-separator has-css-opacity is-style-dots\"\/>\n\n\n\n<p>\ucd94\uac00\uc801\uc73c\ub85c \uc0dd\uac01\ud574\ubcfc \ubb38\uc81c\ub85c Undo \uae30\ub2a5\uc774 \uc788\ub2e4. undo\ub97c \uc704\ud55c \uc804\ub7b5\uc740 \uc0c1\ud669\uc5d0 \ub530\ub77c \uc5ec\ub7ec\uac00\uc9c0\uac00 \uac00\ub2a5\ud558\ub2e4. \uac00\uc5ed\uc801\uc778 command\uc758 \uacbd\uc6b0, \ucee4\ub9e8\ub4dc\ub97c \ubc18\ub300\ub85c \uc2e4\ud589\ud558\ub3c4\ub85d \uad6c\ud604\ud558\uba74 \ub9e4\uc6b0 \uac00\ubccd\uac8c \uc218\ud589\uc774 \uac00\ub2a5\ud574\uc9c4\ub2e4. \uadf8\ub7f0\ub370, \ud56d\uc0c1 \uac00\uc5ed\uc801\uc778\uac8c \uc544\ub2cc\uac8c \ubb38\uc81c\ub2e4. \ud3ec\ud1a0\uc0fe \ud544\ud130\ub97c \uc0dd\uac01\ud574\ubcf4\uba74, \ud544\ud130\uc5f0\uc0b0\uc740 \ube44\uac00\uc5ed\uc801\uc778 \uacbd\uc6b0\uac00 \ub9ce\ub2e4. \uc774 \uacbd\uc6b0, \uc27d\uac8c \uc0dd\uac01\ud560 \uc218 \uc788\ub294\uac74 command\ub97c \uc218\ud589\ud558\uae30 \uc804 \ub2e8\uacc4\uc758 \ubc31\uc5c5\ubcf8\uc744 \ub9cc\ub4e4\uace0 undo\uc2dc \ubc31\uc5c5\ubcf8\uc73c\ub85c \uad50\uccb4\ud558\ub294 \ubc29\ubc95\uc774\ub2e4. \uc774 \uacbd\uc6b0, \ucee4\ub9e8\ub4dc\uac00 \ub298\uc5b4\ub0a0 \uc218\ub85d, \ubc31\uc5c5\ubcf8\uc774 \ub298\uc5b4\ub098 \uc800\uc7a5\uacf5\uac04 \ub610\ub294 \uba54\ubaa8\ub9ac \uc0ac\uc6a9\uc5d0 \uc8fc\uc758\ud574\uc57c \ud560 \uac83\uc774\ub2e4. \ub300\ubd80\ubd84 undo \ub2e8\uacc4\uc5d0 \uc81c\uc57d\uc744 \ub450\ub294 \uc774\uc720\ub294 \uc774\ub7f0 \uc774\uc720\ub85c \uc0dd\uac01\ub41c\ub2e4. \ub9ac\uc5bc\ud0c0\uc784 \ub80c\ub354\ub9c1\uc774 \ub41c\ub2e4\uba74, \ud544\ud130 \ud30c\uc774\ud504\ub77c\uc778\uc5d0\uc11c \ud574\ub2f9 \ud544\ud130\ub9cc \uc81c\uac70\ud558\ub294 \ubc29\ubc95\uc774 \uac00\ub2a5\ud560 \uac83\uc774\ub2e4. \uc774\ub7f0 \uacbd\uc6b0\ub294 \ub9ce\uc9c0 \uc54a\uaca0\uc9c0\ub9cc, \ube14\ub80c\ub354\uc758 \ub178\ub4dc\uc5d0\ub514\ud130\uac19\uc740 \uc791\uc5c5\uc774 \uc774\ub7f0 \ubc29\uc2dd\uc77c \uac83\uc774\ub2e4. <\/p>\n\n\n\n<p>Command Pattern\uc744 \uad6c\ud604\ud574 \ubcf4\ub294\ub370, \uac8c\uc73c\ub974\uae30\ub3c4 \ud588\uc9c0\ub9cc, \uc2dc\uac04\uc774 \uaf64 \uc624\ub798 \uac78\ub838\ub2e4. \ucd94\uc0c1\uc801\uc73c\ub85c \ucc98\uc74c \uc811\ud560 \ub54c \uc27d\ub2e4\uace0 \uc0dd\uac01\ud588\ub294\ub370, \uc9c1\uc811 \uad6c\ud604\ud574\ubcf4\ub2c8 \uc0dd\uac01\ud560 \uc9c0\uc810\ub4e4\uc774 \uc0c1\ub2f9\ud788 \ub9ce\uc558\ub358\uac70 \uac19\ub2e4. \uc5ed\uc2dc, \uc9c1\uc811 \uad6c\ud604\ud574\ubd10\uc57c \ubcf4\uc774\ub294\uac8c \uc788\ub124. 3\uac00\uc9c0 \uc5b8\uc5b4\ub85c \uad6c\ud604\ud558\ub294\uac74 \uadc0\ucc2e\uace0 \uacc4\uc18d \ud5f7\uac08\ub9ac\ub294\ub370, \uc774 \uacfc\uc815\uc774 \uac01 \uc5b8\uc5b4\uc758 \ud2b9\uc9d5\uc744 \ud655\uc2e4\ud558\uac8c \uae30\uc5b5\ud558\uac8c \ub420\uac70\ub77c \ubbff\ub294\ub2e4.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>\uac1d\uccb4\uc5d0\uc11c \ub2e4\ub978 \uac1d\uccb4\ub85c request\ub97c \ubcf4\ub0bc \ub54c, request \ub0b4\uc6a9\uc774 \ubcf5\uc7a1\ud574 \uc9c0\uac70\ub098 \ud655\uc7a5\uc774 \ud544\uc694\ud558\uba74, \ud504\ub85c\ud1a0\ucf5c\uc744 \ub530\ub85c \uc124\uacc4\ud558\uac8c\ub41c\ub2e4. \uadf8\ub807\uac8c \ud574\uc57c \ubcf4\ub2e4 \uc720\uc5f0\ud574\uc9c0\uae30 \ub54c\ubb38\uc774\ub2e4. request\uc5d0 \ub300\ud55c \ud504\ub85c\ud1a0\ucf5c\uc744 \ubcc4\ub3c4\uc758 Command \uc624\ube0c\uc81d\ud2b8\ub85c \uad6c\ud604\ud558\ub294 \ubc29\ubc95\uc774 \ubc14\ub85c Command Pattern\uc774\ub2e4. request\ub97c \ubcf4\ub0b4\ub294 Invoker \uac1d\uccb4\ub294 \uc774\ub97c \ubc1b\ub294 Reciever \uac1d\uccb4\uc5d0 \ub300\ud55c \uc815\ubcf4\uac00 \uc5c6\uc5b4\ub3c4 \ub418\uae30 \ub54c\ubb38\uc5d0(Command \uac1d\uccb4\uac00 \uac16\uace0\uc788\ub2e4), \ub450 \uac1d\uccb4\uac04 coupling\uc744 \uc81c\uac70\ud560 \uc218 \uc788\ub2e4. Command Pattern\uc758 \uc2e4\uc81c [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[6,34,33],"tags":[109,182,183,104,38,35,128,41,55],"class_list":["post-332","post","type-post","status-publish","format-standard","hentry","category-unity","category-kotlin","category-python","tag-c","tag-command","tag-command-pattern","tag-design-pattern","tag-kotlin","tag-python","tag-design-pattern-kr","tag-kotlin-kr","tag-python-kr"],"jetpack_featured_media_url":"","_links":{"self":[{"href":"http:\/\/batmask.net\/index.php\/wp-json\/wp\/v2\/posts\/332","targetHints":{"allow":["GET"]}}],"collection":[{"href":"http:\/\/batmask.net\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/batmask.net\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/batmask.net\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"http:\/\/batmask.net\/index.php\/wp-json\/wp\/v2\/comments?post=332"}],"version-history":[{"count":23,"href":"http:\/\/batmask.net\/index.php\/wp-json\/wp\/v2\/posts\/332\/revisions"}],"predecessor-version":[{"id":3472,"href":"http:\/\/batmask.net\/index.php\/wp-json\/wp\/v2\/posts\/332\/revisions\/3472"}],"wp:attachment":[{"href":"http:\/\/batmask.net\/index.php\/wp-json\/wp\/v2\/media?parent=332"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/batmask.net\/index.php\/wp-json\/wp\/v2\/categories?post=332"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/batmask.net\/index.php\/wp-json\/wp\/v2\/tags?post=332"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}