π‘ μ± μ μ°μ(Chain of Responsibility) ν¨ν΄μ΄λ?
νΈλ€λ¬λ€μ 체μΈ(μ¬μ¬)μ λ°λΌ μμ²μ μ λ¬ν μ μκ² ν΄μ£Όλ νλ λμμΈ ν¨ν΄μ λλ€. ν΄λΌμ΄μ΄νΈμ μμ²μ λν μΈμΈν μ²λ¦¬λ₯Ό νλμ κ°μ²΄κ° λͺ½λ νλ κ²μ΄ μλ, μ¬λ¬ κ°μ μ²λ¦¬ κ°μ²΄λ€λ‘ λλκ³ , μ΄λ€μ μ¬μ¬(chain)μ²λΌ μ°κ²°ν΄ μ§ν© μμμ μ°μμ μΌλ‘ μ²λ¦¬νλ νλ ν¨ν΄μ λλ€.
μ΄λ¬ν μ²λ¦¬ κ°μ²΄λ€μ νΈλ€λ¬(handler)λΌκ³ λΆλ₯΄λλ°, μμ²μ λ°μΌλ©΄ κ° νΈλ€λ¬λ μμ²μ μ²λ¦¬ν μ μλμ§ νλ¨νκ³ , μμΌλ©΄ 체μΈμ λ€μ νΈλ€λ¬λ‘ μ²λ¦¬μ λν μ± μμ μ κ°ν©λλ€.
μ²λ¦¬μ λν μ± μμ μμ²μ 보λ΄λ μͺ½(sender)κ³Ό μμ²μ μ²λ¦¬νλ(receiver) μͺ½μ λΆλ¦¬νμ¬ κ° κ°μ²΄λ₯Ό λΆνμΌλ‘ λ 립μν€κ³ κ²°ν©λλ₯Ό λμ¨νκ² λ§λ€λ©°, μν©μ λ°λΌμ μμ²μ μ²λ¦¬ν κ°μ²΄κ° λ³νλ νλ‘κ·Έλ¨μλ μ μ°νκ² λμν μ μλ€λ μ₯μ μ κ°μ§κ³ μμ΅λλ€.
π‘ ν΄λμ€ λ€μ΄μ΄κ·Έλ¨μΌλ‘ λ³Έ μ± μ μ°μ ν¨ν΄
- Handler : μμ²μ μμ νκ³ μ²λ¦¬ κ°μ²΄λ€μ μ§ν©μ μ μνλ μΈν°νμ΄μ€μ΄λ€.
- BaseHandler : λͺ¨λ νΈλ€λ¬ ν΄λμ€λ€μ λ¬Άλ μΆμ ν΄λμ€λ‘, μ νμ μ΄λ€.
- ConcreteHandler : μμ²μ μ²λ¦¬νλ μ€μ μ²λ¦¬ κ°μ²΄λ‘, νΈλ€λ¬μ λν νλλ₯Ό λ΄λΆμ κ°μ§κ³ μμΌλ©° λ©μλλ₯Ό ν΅ν΄ λ€μ νΈλ€λ¬λ₯Ό 체μΈμν€κ³ λ€μ λ°λΌλ³Έλ€. μμ μ΄ μ²λ¦¬ν μ μλ μκ΅¬κ° λμ€λ©΄ λ°λΌλ³΄κ³ μλ λ€μ 체μΈμ νΈλ€λ¬μκ² μμ²μ λ λκΈ΄λ€. ConcreteHandler1 - ConcreteHandler2 - ConcreteHandler3 - ... μ΄λ°μμΌλ‘ μ²΄μΈ νμμ΄ κ΅¬μ±λκ² λλ€.
- Client : μμ²μ Handlerμκ² μ λ¬νλ€. μμ²μ λͺ¨λ νΈλ€λ¬μ λ³΄λΌ μ μκ³ , κΌ μ²« λ²μ§Έ νΈλ€λ¬μΌ νμλ μλ€.
π‘ μ± μ μ°μ ν¨ν΄ ꡬν
- Base Handler
// ꡬ체μ μΈ νΈλ€λ¬λ₯Ό λ¬Άλ μΈν°νμ΄μ€ (μΆμ ν΄λμ€)
abstract class Handler {
// λ€μ 체μΈμΌλ‘ μ°κ²°λ νΈλ€λ¬
protected Handler nextHandler = null;
// μμ±μλ₯Ό ν΅ν΄ μ°κ²°μν¬ νΈλ€λ¬λ₯Ό λ±λ‘
public Handler setNext(Handler handler) {
this.nextHandler = handler;
return handler; // λ©μλ 체μ΄λ ꡬμ±μ μν΄ μΈμλ₯Ό κ·Έλλ‘ λ°νν¨
}
// μμ νΈλ€λ¬μμ ꡬ체ν νλ μΆμ λ©μλ
protected abstract void process(String url);
// νΈλ€λ¬κ° μμ²μ λν΄ μ²λ¦¬νλ λ©μλ
public void run(String url) {
process(url);
// λ§μΌ νΈλ€λ¬κ° μ°κ²°λκ² μλ€λ©΄ λ€μ νΈλ€λ¬λ‘ μ±
μμ λ λκΈ΄λ€
if (nextHandler != null)
nextHandler.run(url);
}
}
- Concrete Handler
class ProtocolHandler extends Handler {
@Override
protected void process(String url) {
int index = url.indexOf("://");
if (index != -1) {
System.out.println("PROTOCOL : " + url.substring(0, index));
} else {
System.out.println("NO PROTOCOL");
}
}
}
class DomianHandler extends Handler {
@Override
protected void process(String url) {
int startIndex = url.indexOf("://");
int lastIndex = url.lastIndexOf(":");
System.out.print("DOMAIN : ");
if (startIndex == -1) {
if (lastIndex == -1) {
System.out.println(url);
} else {
System.out.println(url.substring(0, lastIndex));
}
} else if (startIndex != lastIndex) {
System.out.println(url.substring(startIndex + 3, lastIndex));
} else {
System.out.println(url.substring(startIndex + 3));
}
}
}
class PortHandler extends Handler {
@Override
protected void process(String url) {
int index = url.lastIndexOf(":");
if (index != -1) {
String strPort = url.substring(index + 1);
try {
int port = Integer.parseInt((strPort));
System.out.println("PORT : " + port);
} catch (NumberFormatException e) {
e.printStackTrace();
}
}
}
}
- Client
class Client {
public static void main(String[] args) {
// 1. νΈλ€λ¬ μμ±
Handler handler1 = new ProtocolHandler();
Handler handler2 = new DomianHandler();
Handler handler3 = new PortHandler();
// 2. νΈλ€λ¬ μ°κ²° μ€μ (handler1 → handler2 → handler3)
handler1.setNext(handler2).setNext(handler3);
// 3. μμ²μ λν μ²λ¦¬ μ°μ μ€ν
String url1 = "<http://www.youtube.com:80>";
System.out.println("INPUT: " + url1);
handler1.run(url1);
System.out.println();
String url2 = "<https://www.inpa.tistory.com:443>";
System.out.println("INPUT: " + url2);
handler1.run(url2);
System.out.println();
String url3 = "";
System.out.println("INPUT: " + url3);
handler1.run(url3);
}
}
π‘ λ§λ¬΄λ¦¬
μ± μ μ°μ ν¨ν΄μ
- νΉμ μμ²μ 2κ° μ΄μμ μ¬λ¬ κ°μ²΄μμ νλ³νκ³ μ²λ¦¬ν΄μΌ ν λ
- νΉμ μμλ‘ μ¬λ¬ νΈλ€λ¬λ₯Ό μ€νν΄μΌ ν λ
- νλ‘κ·Έλ¨μ΄ λ€μν λ°©μκ³Ό μ’ λ₯μ μμ²μ μ²λ¦¬ν κ²μΌλ‘ μμλμ§λ§ μ νν μμ² μ νκ³Ό μμλ₯Ό 미리 μ μ μμ λ
- μμ²μ μ²λ¦¬ν μ μλ κ°μ²΄ μ§ν©μ΄ λμ μΌλ‘ μ μλμ΄μΌ ν λ (μ²΄μΈ μ°κ²°μ λ°νμμμ λμ μΌλ‘ μ€μ )
μ μ¬μ©ν μ μμ΅λλ€.
μ± μ μ°μ ν¨ν΄μ μ¬μ©νλ©΄ ν΄λΌμ΄μΈνΈλ μ²λ¦¬ κ°μ²΄μ μ²΄μΈ μ§ν© λ΄λΆμ ꡬ쑰λ₯Ό μ νμκ° μκ³ , κ°κ°μ 체μΈμ μμ μ΄ ν΄μΌνλ μΌλ§ νκΈ° λλ¬Έμ μλ‘μ΄ μμ²μ λν μ²λ¦¬ κ°μ²΄ μμ±μ΄ νΈλ¦¬ν΄μ§λλ€(SRP μ€μ). λν, κΈ°μ‘΄ ν΄λΌμ΄μΈνΈ μ½λλ₯Ό λ³κ²½νμ§ μκ³ νΈλ€λ¬λ₯Ό 체μΈμ λμ μΌλ‘ μΆκ°νκ±°λ μ²λ¦¬ μμλ₯Ό λ³κ²½νκ±°λ μμ ν μ μμ΅λλ€(OCP μ€μ).
κ·Έλ¬λ, μμ²μ΄ λ°λμ μνλλ€λ 보μ₯μ΄ μμ΅λλ€. (μ²΄μΈ λκΉμ§ κ°λλ°λ μ²λ¦¬λμ§ μμ μ μμ.)