메시지 송신측과 수신측을 분리하여 요청을 처리하는 기회를 다른 객체에 분산한다. 요청이 들어오면 해당 요청을 처리할 수 있는 객체를 찾을 때까지 연결 고리를 따라 요청을 전달하고, 적합한 객체를 발견하면 요청한 서비스를 제공하는 행위 패턴
- Handler : 요청을 처리하는 인터페이스를 정의하고, 다음 객체에게 메시지 전송
- ConcreteHandler : 해당 요청을 처리할 수 있는 경우 직접 처리
- Client : ConcreteHandler 객체에게 필요한 요청 전송
ATM 기기에서 돈을 인출한다고 가정해보자. 책임연쇄 패턴을 이용하면
10만원, 5만원, 1만원 단위로 인출이 가능하다.
만약, 천원권 이하의 단위로 입력하면 다시 입력하게 한다.
[WithdrawChain.java]
public abstract class WithdrawChain {
WithdrawChain withdrawChain;
WithdrawChain setNext(WithdrawChain withdrawChain) {
this.withdrawChain = withdrawChain;
return withdrawChain;
}
abstract void withdraw(Currency currency);
}
[Currency.java] - Dto 객체
public class Currency {
private int amount;
public Currency(int money) {
this.amount = money;
}
public int getAmount() {
return amount;
}
}
[Withdraw100000Won.java]
public class Withdraw100000Won extends WithdrawChain {
@Override
public void withdraw(Currency currency) {
if (currency.getAmount() % 10000 != 0) {
System.out.println("10000원 단위로 다시 입력해 주세요");
return;
}
if (currency.getAmount() >= 100000) {
int cnt = currency.getAmount() / 100000;
System.out.println("10만원짜리 " + cnt + "장이 인출 되었습니다.");
int remainder = currency.getAmount() % 100000;
if (remainder != 0) {
this.withdrawChain.withdraw(new Currency(remainder));
}
} else {
this.withdrawChain.withdraw(currency);
}
}
}
[Withdraw50000Won.java]
public class Withdraw50000Won extends WithdrawChain {
@Override
public void withdraw(Currency currency) {
if (currency.getAmount() >= 50000) {
int cnt = currency.getAmount() / 50000;
System.out.println("5만원짜리 " + cnt + "장이 인출 되었습니다.");
int remainder = currency.getAmount() % 50000;
if (remainder != 0) {
this.withdrawChain.withdraw(new Currency(remainder));
}
} else {
this.withdrawChain.withdraw(currency);
}
}
}
[Withdraw10000Won.java]
public class Withdraw10000Won extends WithdrawChain {
@Override
public void withdraw(Currency currency) {
if (currency.getAmount() >= 10000) {
int cnt = currency.getAmount() / 10000;
System.out.println("1만원짜리 " + cnt + "장이 인출 되었습니다.");
int remainder = currency.getAmount() % 10000;
if (remainder != 0) {
this.withdrawChain.withdraw(new Currency(remainder));
}
} else {
this.withdrawChain.withdraw(currency);
}
}
}
[Client.java]
public class Client {
public static void main(String[] args) throws IOException {
// 체이닝 방식 1
WithdrawChain withdraw100000Won = new Withdraw100000Won();
withdraw100000Won.setNext(new Withdraw50000Won())
.setNext(new Withdraw10000Won());
// 체이닝 방식 2
// Withdraw50000Won withdraw50000Won = new Withdraw50000Won();
// Withdraw10000Won withdraw10000Won = new Withdraw10000Won();
// withdraw100000Won.setNext(withdraw50000Won);
// withdraw50000Won.setNext(withdraw10000Won);
while (true) {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
System.out.println("인출할 금액을 적어주세요.");
int money = Integer.parseInt(br.readLine());
if (money <= 0) {
System.out.println("종료하겠습니다.");
break;
}
Currency currency = new Currency(money);
withdraw100000Won.withdraw(currency);
System.out.println("--------------------------");
}
}
}
장점
단점