한번에 여러 곳에 메시지를 발송하는 프로그램을 개발하자.
Sender
인터페이스를 사용하세요.EmailSender
, SmsSender
, FacebookSender
를 구현하세요.package poly.ex.sender;
public class SendMain {
public static void main(String[] args) {
Sender[] senders = {new EmailSender(), new SmsSender(), new FaceBookSender()};
for (Sender sender : senders) {
sender.sendMessage("환영합니다!");
}
}
}
package poly.ex.sender;
public interface Sender {
void sendMessage(String message);
}
package poly.ex.sender;
public class EmailSender implements Sender {
@Override
public void sendMessage(String message) {
System.out.println("메일을 발송합니다 : " + message);
}
}
package poly.ex.sender;
public class SmsSender implements Sender {
@Override
public void sendMessage(String message) {
System.out.println("SMS를 발송합니다 : " + message);
}
}
package poly.ex.sender;
public class FaceBookSender implements Sender {
@Override
public void sendMessage(String message) {
System.out.println("페이스북에 발송합니다 : " + message);
}
}
여러분은 기대하던 결제 시스템 개발팀에 입사하게 되었다.
이 팀은 현재 2가지 결제 수단을 지원한다. 앞으로 5개의 결제 수단을 추가로 지원할 예정이다.
새로운 결제 수단을 쉽게 추가할 수 있도록, 기존 코드를 리팩토링해라.
PayMain0
코드는 변경하지 않고, 그대로 유지해야 합니다.package poly.ex.pay0;
public class KakaoPay {
public boolean pay(int amount) {
System.out.println("카카오페이 시스템과 연결합니다.");
System.out.println(amount + "원 결제를 시도합니다.");
return true;
}
}
package poly.ex.pay0;
public class NaverPay {
public boolean pay(int amount) {
System.out.println("네이버페이 시스템과 연결합니다.");
System.out.println(amount + "원 결제를 시도합니다.");
return true;
}
}
package poly.ex.pay0;
public class PayService {
public void processPay(String option, int amount) {
boolean result;
System.out.println("결제를 시작합니다 : option = " + option + ", amount = " + amount);
if (option.equals("kakao")) {
KakaoPay kakaoPay = new KakaoPay();
result = kakaoPay.pay(amount);
} else if (option.equals("naver")) {
NaverPay naverPay = new NaverPay();
result = naverPay.pay(amount);
} else {
System.out.println("결제 수단이 없습니다.");
result = false;
}
if (result) {
System.out.println("결제가 성공했습니다.");
} else {
System.out.println("결제가 실패했습니다.");
}
}
}
package poly.ex.pay0;
public class PayMain0 {
public static void main(String[] args) {
PayService payService = new PayService();
// kakao 결제
String payOption1 = "kakao";
int amount1 = 5000;
payService.processPay(payOption1, amount1);
// naver 결제
String payOption2 = "naver";
int amount2 = 10000;
payService.processPay(payOption2, amount2);
// 잘못된 결제 수단 선택
String payOption3 = "bad";
int amount3 = 15000;
payService.processPay(payOption3, amount3);
}
}
이 문제에 정답은 없습니다.
새로운 결제 수단을 추가했을 때 Pay
를 사용하는 클라이언트 코드인 PayService
의 변경을 최소화 할 수 있다면 성공입니다.
package poly.ex.pay1;
public interface Pay {
boolean pay(int amount);
}
package poly.ex.pay1;
public class KakaoPay implements Pay {
@Override
public boolean pay(int amount) {
System.out.println("카카오페이 시스템과 연결합니다.");
System.out.println(amount + "원 결제를 시도합니다.");
return true;
}
}
package poly.ex.pay1;
public class NaverPay implements Pay {
@Override
public boolean pay(int amount) {
System.out.println("네이버페이 시스템과 연결합니다.");
System.out.println(amount + "원 결제를 시도합니다.");
return true;
}
}
package poly.ex.pay1;
public class DefaultPay implements Pay {
@Override
public boolean pay(int amount) {
System.out.println("결제 수단이 없습니다.");
return false;
}
}
DefaultPay
사용하면 null
체크를 피할 수 있다.package poly.ex.pay1;
public abstract class PayStore {
// 결제 수단 추가시 변하는 부분
public static Pay findPay(String option) {
if (option.equals("kakao")) {
return new KakaoPay();
} else if (option.equals("naver")) {
return new NaverPay();
} else {
return new DefaultPay();
}
}
}
static
으로 기능을 제공한다. 추상 클래스로 선언해서 객체 생성을 막는다.null
대신에 항상 실패하는 결제 수단을 사용한다.package poly.ex.pay1;
public class PayService {
public void processPay(String option, int amount) {
System.out.println("결제를 시작합니다 : option = " + option + ", amount = " + amount);
Pay pay = PayStore.findPay(option);
boolean result = pay.pay(amount);
if (result) {
System.out.println("결제가 성공했습니다.");
} else {
System.out.println("결제가 실패했습니다.");
}
}
}
PayService
는 구체적인 결제 수단이 아니라 Pay
에 의존한다.PayService
의 코드에는 변경이 없다.package poly.ex.pay1;
public class PayMain1 {
public static void main(String[] args) {
PayService payService = new PayService();
// kakao 결제
String payOption1 = "kakao";
int amount1 = 5000;
payService.processPay(payOption1, amount1);
// naver 결제
String payOption2 = "naver";
int amount2 = 10000;
payService.processPay(payOption2, amount2);
// 잘못된 결제 수단 선택
String payOption3 = "bad";
int amount3 = 15000;
payService.processPay(payOption3, amount3);
}
}
기존 결제 시스템이 사용자 입력을 받도록 수정하세요.
package poly.ex.pay1;
import java.util.Scanner;
public class PayMain2 {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
PayService payService = new PayService();
while (true) {
System.out.print("결제 수단을 입력하세요 : ");
String payOption = scanner.nextLine();
if (payOption.equals("exit")) {
System.out.println("프로그램을 종료합니다.");
return;
}
System.out.print("결제 금액을 입력하세요 : ");
int amount = scanner.nextInt();
scanner.nextLine();
payService.processPay(payOption, amount);
}
}
}
출처 : 김영한의 실전 자바 - 기본편
https://www.inflearn.com/course/김영한의-실전-자바-기본편/dashboard