커맨드패턴(Command Pattern)
보면 알겠지만 커맨드(명령)을 login/logout명령으로 나눠서 따로 구현했다.
구현할 때 Command 인터페이스를 구현하여 execute(실행해라!)모든 명령을 이 인터페이스가 있는 녀석으로 구현하면
뭐든 간에 execute만 실행하면 될 것이다.
(defn login [id pass] (println "id: " id ", pass: " pass)) (defn logout [id] (println "logout: " id)) (defn execute [command] (do (println "logging") (command))) ;; 익명인터페이스와 동급 (execute #(login "name" "123")) (execute #(logout "idid")) (defn execute [command & args] (apply command args)) (execute login "id" "password")apply를 사용하는 이유는 [command & args]에서 args는 리스트형태(?)로 반환하기 때문에 이 리스트 괄호를 깨부시고 안에 들어가서 적용(apply)해야 한다.
(defn wrong-execute [command & args] (command args)) (wrong-execute login "id" "password") ArityException Wrong number of args (1) passed to: user/login clojure.lang.AFn.throwArity (AFn.java:429)보는바와 같이 login에는 잘못된 숫자의 매개변수가 들어간 것이다.
아마
(login ["id" "password"])요래 들어갔을 것이다. 이렇게 실행해보자.
user=> (login ["id" "password"]) ArityException Wrong number of args (1) passed to: user/login clojure.lang.AFn.throwArity (AFn.java:429)똑같다 이제 apply를 해보자
user=> (apply login ["id" "password"]) id: id , pass: password nil아까 apply를 이용하면 괄호들을 깨부수고 안으로 들어(?)간다고 했다.
(apply login ["id" "password"]) == (login "id" "password")요래 들어가는 것!!! (apply를 꼭 써야 한다.)
============================
이게 왜 중요하다는 거지?
일단 커맨트패턴이 뭔지보자. (자바의 눈으로)execute()하나를 함께 쓰기 위해서 Command라는 인터페이스를 각각 구현하는 것이다.
그러면 login/logout을 하기 위해 login,logout클래스를 만들고 Command라는 인터페이스를 구현할 것이다.
자 그렇다면 로그인을 위한 Command 인터페이스를 클래스로 구현했다. 그리고 이제 이 클래스를 사용할 것이다.
아니!
정확히는 이 클래스에 있는 Command 안에 execute을 사용할 것이다.
이 커맨드들을 어딘가에 뒀다가 가져오려면 리턴도 되야하고 매개변수로 넣어지기도 해야 할것이다.
클래스는 그럴 수 없다.(뭔줄알고!!) 메소드를 넣을 수도 없다. 인터페이스를 넣는 것이다.
execute를 사용하기 위해!!
클로저의 눈으로 보자.
일단 클로저에서는 함수를 그냥 넘기기 때문에 개념이 아예 다르다.
그냥... 뭔 만들고 넣고 하는게 아니라...
함수를 보내고 받은걸 쓰면 된다.
뭐가 더 좋다가 아니라 이 두 개념을 마음대로 노닐 수 있는 내가 되었으면 좋겠다.