팩토리 패턴은 객체를 사용하는 코드에서 객체 생성 부분을 떼어내 추상화한 패턴
상속 관계에 있는 두 클래스에서 상위 클래스가 중요한 뼈대를 결정하고
하위 클래스에서는 객체 생성에 관한 구체적인 내용을 결정하는 패턴이다.
예를 들어 커피 공장이 있다고 생각하게 되면
구체적인 레시피 들이 들어 있는 하위 클래스가 전달이 되고 이 레시피들을
토대로 제품들이 생산되는 것을 생각하면 된다.
밑의 코드를 통해 자세히 알아보자.
abstract class Coffee {
public abstract int getPrice();
@Override
public String toString() {
return "Hi this coffee is " + this.getPrice();
}
}
class CoffeeFactory{
public static Coffee getCoffee(String type, int price){
if("Latte".equalsIgnoreCase(type)) return new Latte(price);
else if("Americano".equalsIgnoreCase(type)) return new Americano(price);
else{
return new DefaulCoffee();
}
}
}
class DefaulCoffee extends Coffee{
private int price;
public DefaulCoffee(){
this.price = -1;
}
@Override
public int getPrice() {
return this.price;
}
}
class Latte extends Coffee{
private int price;
public Latte(int price){
this.price = price;
}
@Override
public int getPrice() {
return this.price;
}
}
class Americano extends Coffee{
private int price;
public Americano(int price){
this.price = price;
}
@Override
public int getPrice() {
return this.price;
}
}
/*
커피 팩토리라는 커피를 생성하는 클래스가 있고
그 클래스에는 라떼와 아메리카노 defalutCoffee를 받고 있다
커피 종류와 가격을 적으면 그에 맞게 출력되는 시스템
*/
public class HelloWorld {
public static void main(String[] args) {
Coffee latte = CoffeeFactory.getCoffee("Latte", 5500);
Coffee americano = CoffeeFactory.getCoffee("americano", 5500);
System.out.println("Factory latte:: " + latte);
System.out.println("Factory americano:: " + americano);
}
}
전략 패턴은 정책 패턴이라고도 하며, 객체의 행위를 바꾸고 싶은 경우
직접 수정하지 않고, 전략이라고 부르는 캡슐화한 알고리즘을 컨텍스트
안에서 바꿔주면서 상호 교체가 가능하게 만드는 패턴이다.
※ 컨텍스트란?
프로그래밍에서는 컨텍스트는 상황, 맥락, 문맥을 의미하며 개발자가
어떤 작업을 완료하는데 필요한 모든 관련 정보를 말한다.
다음예제는 우리가 어떤 상품을 구매할 때 네이버페이나 카카오페이등
다양한 결제 시스템이 있듯이 LUNACard로 사는 것과 KAKAOCard로
사는 것을 구현한 예제입니다.
interface PaymentStrategy {
public void pay(int amount);
}
class KAKAOCardStrategy implements PaymentStrategy {
private String name;
private String cardNumber;
private String cvv;
private String date0fExpiry;
public KAKAOCardStrategy(String name, String cardNumber, String cvv, String date0fExpiry){
this.name = name;
this.cardNumber = cardNumber;
this.cvv = cvv;
this.date0fExpiry = date0fExpiry;
}
@Override
public void pay(int amount) {
System.out.println(amount + " paid using KAKAOCard.");
}
}
class LUNACardStrategy implements PaymentStrategy {
private String emailId;
private String password;
public LUNACardStrategy(String emailId, String password) {
this.emailId = emailId;
this.password = password;
}
@Override
public void pay(int amount) {
System.out.println(amount + " paid using LUNACard.");
}
}
class Item{
private String name;
private int price;
public Item(String name, int cost) {
this.name = name;
this.price = cost;
}
public String getName() {
return name;
}
public int getPrice() {
return price;
}
}
class ShoppingCart{
List<Item> items;
public ShoppingCart() {
this.items = new ArrayList<Item>();
}
public void addItem(Item item){
this.items.add(item);
}
public void removeItem(Item item){
this.items.remove(item);
}
public int calculateTotal(){
int sum = 0;
for (Item item: items){
sum += item.getPrice();
}
return sum;
}
public void pay(PaymentStrategy paymentMethod){
int amount = calculateTotal();
paymentMethod.pay(amount);
}
}
public class HelloWorld {
public static void main(String[] args) {
ShoppingCart cart = new ShoppingCart();
Item A = new Item("kundolA", 100);
Item B = new Item("kundolB", 300);
cart.addItem(A);
cart.addItem(B);
// pay by LUNACard
cart.pay(new LUNACardStrategy("kundol@example.com", "pukubababo"));
// pay by KAKAOCard
cart.pay(new KAKAOCardStrategy("Ju hongchul", "123456789","123","12/01"));
// 위의 코드는 쇼핑카트에 아이템을 담고 LUNACard와 KAKAOCard라는 두개의
// 전략으로 결제하는 코드이다.
}
}