2018년 3월 5일 월요일

[clojure][designpattern]책임 연쇄(Chain Of Responsibility) 패턴

비속어를 별표로 변하는 필터를 만들자.
public abstract class Filter {
  protected Filter nextFilter;

  abstract void process(String message);

  public void setNextFilter(Filter nextFilter) {
    this.nextFilter = nextFilter;
  }
}
실제 적용할 필터
class LogFilter extends Filter {
  @Override
  void process(String message) {
    Logger.info(message);
    if (nextFilter != null) nextFilter.process(message);
  }
}

class Profanityfilter extends Filter {
  @Override
  void process(String message) {
    String newMessage = message.replaceAll("fuck","f*ck");
    if (nextFilter != null) nextFilter.process(newMessage);
  }
}

class RejectFilter extends Filter {
  @Override
  void process(String message) {
    System.out.println("RejectFilter");
    if (message.startsWith("[A Project NY]")) {
      if (nextFilter. != null) nextFilter.process(message);
    }
  }
}

class StatisticsFilter extends Filter {
  @Override
  void process(String message) {
    Statistics.addUsedChars(message.length());
    if (nextFilter != null) nextFilter.process(message);
  }
}
1. 각 필터를 만든다. 2. 서로 기차놀이처럼 연결한다. (순서를 만드는 것이다)
Filter rejectFilter = new RejectFilter();
Filter logFilter = new LogFilter();
Filter profanityFilter = new ProfanityFilter();
Filter statsFilter = new StatisticsFilter();

rejectFilter.setNextFilter(logFilter);
logFilter.setNextFilter(profanityFilter);
profanityFilter.setNextFilter(statsFilter);

String message = "[A PROFIT NY] What the fuck?";
rejectFilter.process(message);
clojure 클로저는 각 필터를 함수로 만든다.
;; define filters

(defn log-filter [message]
  (logger/log message)
  message)

(defn stats-filter [message]
  (stats/add-used-chars (count message))
  message)

(defn profanity-filter [message]
  (clojure.string/replace message "fuck" "f*ck"))

(defn reject-filter [message]
  (if (.startsWith message "[A Profit NY]")
    message))
(defn chain [message]
  (some-> message
          reject-filter
          log-filter
          stats-filter
          profanity-filter))
저 some->가 뭐지? some->는 ->와 기능이 같다.
한가지만 빼고 표현식이 nil이면 멈춘다. 그리고 nil을 내뱉는다. nil이 아니면 값을 다음에 넘긴다.
(chain "fuck") => nil
(chain "[A Profit NY] fuck") => "f*ck"
[A profit NY] 가 없으면 reject-filter에서 이미 걸려서 nil이 나옴.

댓글 없음:

댓글 쓰기