๐ ๋ค์ด๊ฐ๋ฉฐ
๋์์ธ ๋ฉ์๋ ํจํด์ ์ด๋ฒ ์ด์ง์ ์ํด ๊ฐ๋ฐํ๋ ์ฌ์ ๊ณผ์ ์๋น์ค์์๋ ๊ทธ๋ ๊ณ ์ค๋ฌด์์๋ ์ ๋ง ๋ง์ด ์ฌ์ฉํ๊ณ ์๋ ํจํด์ ๋๋ค. ๊ทธ๋งํผ ํ์ฅ์ฑ์ด ์ข๊ธฐ ๋๋ฌธ์ ๊ณ์ ํ์ฉํ๊ฒ ๋๋ ๊ฒ ๊ฐ์๋ฐ ์ด๋ก ์ ์ผ๋ก๋ ํ๋ฒ๋ ์ ๋ฆฌํด๋ณธ ์ ์ด ์์ด ์ด๋ฒ ํฌ์คํ ์ ํตํด ์ด๋ก ์ ์ธ ๋ด์ฉ์ ์ ๋ฆฌํด๋๋ ค๊ณ ํฉ๋๋ค.
Factory Method Pattern(ํฉํ ๋ฆฌ ๋ฉ์๋ ํจํด)
ํฉํ ๋ฆฌ ๋ฉ์๋ ํจํด์ ์์ ํด๋์ค์์ ๊ฐ์ฒด์ ์ธํฐํ์ด์ค๋ฅผ ์ ์ํ๊ณ , ํ์ ํด๋์ค๊ฐ ๊ฐ์ฒด๋ฅผ ์์ฑํ ์ง๋ฅผ ๊ฒฐ์ ํ๋๋ก ํ๋ ํจํด์ ๋๋ค. ๊ฐ์ฒด๋ฅผ ํ์ ํด๋์ค์์ ์์ฑ๋๋๋ก ์ํค๋ ๊ฒ์ด์ฃ . ์ด๋ ๋ค์ ๋งํด ๋ถ๋ชจ ํด๋์ค์์ ๊ฐ์ฒด๋ค์ ์์ฑํ ์ ์๋ ์ธํฐํ์ด์ค๋ฅผ ์ ๊ณตํ์ง๋ง, ์์ ํด๋์ค๋ค์ด ์์ฑ๋ ๊ฐ์ฒด๋ค์ ์ ํ์ ๋ณ๊ฒฝํ ์ ์๋๋ก ํ๋ ์์ฑ ํจํด์ ๋๋ค.
์ด๋ฌํ Factory Method Pattern๋ Factory์ Template Method Pattern์ด ๊ฒฐํฉ๋ ํํ์ ๋๋ค.
vs Simple Factory
Factory Method Pattern์ Simple Factory์ ์ถ์ํ๊ฐ ๋ํด์ง ๊ฐ๋ ์ ๋๋ค.
Simple Factory๋ ๋ถ๋ฆฌ๋ ํด๋์ค์ ์์ฑ ์ฝ๋๋ฅผ ์ง์ ๊ตฌํํ๋ค๋ฉด,
Factory Method๋ ์ถ์ํ๋ ์์ ํด๋์ค ์ธํฐํ์ด์ค๋ฅผ ํ์ ํด๋์ค์์ ์ง์ ๊ฐ์ฒด๋ฅผ ์์ฑํฉ๋๋ค.
vs Template Method
Factory Method ํจํด์ Template Method ํจํด๊ณผ ์ ์ฌํ ๋ชจ์ต์ ๊ฐ์ง๊ณ ์์ต๋๋ค.
Factory Method๋ ์ค์ ์์ฑ๋๋ ์๊ณ ๋ฆฌ์ฆ์ ํ์ ๋ฉ์๋๋ก ์์ํ๋๋ฐ, ์ค์ ๊ตฌํ์ ์์ํ๋ค๋ ์ธก๋ฉด์์ Template Method ํจํด๊ณผ ์ ์ฌํ๋ค๊ณ ๋ณผ ์ ์์ต๋๋ค.
Template Method ๊ณผ์ ๊ด๊ณ๋ฅผ ์ ๋ฆฌํ์๋ฉด,
๊ณตํต์ : ์ถ์ํ๋ฅผ ์ฌ์ฉํด ๊ฐ์ฒด๋ฅผ ์์ฑํ๋ฉฐ, ์์ ํด๋์ค์์ ์ ์๋ฅผ ๊ฒฐ์ ํ๊ณ ํ์ ํด๋์ค์ ๊ตฌ์ฒด์ ์ธ ์ฒ๋ฆฌ๋ฅผ ์์ํฉ๋๋ค.
์ฐจ์ด์ : ํด๊ฒฐํ๋ ค๋ ๋ชฉ์ ์ ๋ฐ๋ผ ๋ ํจํด์ ์ฐจ์ด๊ฐ ์์ต๋๋ค.
Parameterized
Parameterized Factory Method
๋งค๊ฐ๋ณ์ ํฉํ ๋ฆฌ๋ ์ ๋ ฅ ๋งค๊ฐ๋ณ์์ ๋ฐ๋ผ ๋ค๋ฅธ ํด๋์ค์ ๊ฐ์ฒด๋ฅผ ๋ฐํํ๋ ๊ธฐ๋ฅ์ ๋งํฉ๋๋ค.
๋ํ ํ๋ก๊ทธ๋จ์ ๊ฐ๋ฐํ๋ค ๋ณด๋ฉด ์๊ฐ๋ณด๋ค ๋ง์ ์์ ๊ฐ์ฒด๋ฅผ ์์ฑํด์ผ ํ๊ธฐ๋ ํ๊ณ ,
๊ฐ์ฒด ๊ด๊ณ ์ค์ ์ด ๋ณต์กํด์ง๊ณ ๊ฐ์ฒด ์์ฑ์ ์ฒ๋ฆฌํ๋ ์ฝ๋ ์์น๋ ๋ถ์ฐ๋ฉ๋๋ค.
ํฉํ ๋ฆฌ ๋ฉ์๋์์ ์ ๋ ฅ๋ฐ์ ๋งค๊ฐ๋ณ์๋ฅผ ์ฒ๋ฆฌํ ๋ ๋งค๊ฐ๋ณ์์ ๋ง๋ ํด๋์ค๋ฅผ ์ ํํ์ฌ ๊ฐ์ฒด๋ฅผ ์์ฑํฉ๋๋ค.
public abstract class Pizza {
public abstract decimal GetPrice();
public enum PizzaType {
HamMushroom, Deluxe, Seafood
}
public static Pizza PizzaFactory(PizzaType pizzaType) {
switch (pizzaType) {
case PizzaType.HamMushroom:
return new HamAndMushroomPizza();
case PizzaType.Deluxe:
return new DeluxePizza();
case PizzaType.Seafood:
return new SeafoodPizza();
}
throw new System.NotSupportedException("The pizza type " + pizzaType.ToString() + " is not recognized.");
}
}
Factory Method ํน์ง
โ๏ธ DIP, Dependency Inversion Principle.(์์กด ๊ด๊ณ ์ญ์ ์ ์์น)
DIP๋ ๊ตฌ์ฒดํ์ ์์กดํ์ง ๋ง๊ณ ์ถ์ํ์ ์์กดํ๋ผ๋ ์์น์ ๋๋ค.
Factory Method๋ ์ถ์ํ๋ ๊ฐ์ฒด๋ฅผ ์ ์ํด์ ํ์ ํด๋์ค์์ ๊ตฌํํ๋ ํจํด์ ๋๋ค.
Factory Method๋ DIP ์์น์ ์ ๊ตฌํํ ์ฌ๋ก์ ๋๋ค.
โ๏ธ ์์กด์ฑ
์์ฑ ํจํด์ ๊ฐ์ฒด์ ์์ฑ ๊ณผ์ ์ ์ธ๋ถ์ ๊ณต๊ฐํ์ง ์๊ธฐ ์ํด ์ฌ์ฉํฉ๋๋ค.
์ง์ ์ ์ผ๋ก new ํค์๋๋ฅผ ์ฌ์ฉํ๋ ๋น๋๊ฐ ์ค์ด๋ค๊ฒ ๋ฉ๋๋ค.
๋์จํ ๊ฒฐํฉ์ผ๋ก ์์กด์ฑ์ ์ค์ผ ์ ์์ต๋๋ค.
โ๏ธ ์บก์ํ์ ๊ด๋ฆฌ
ํฉํ ๋ฆฌ ๋ฉ์๋ ํจํด์ ํด๋์ค ๊ฒฐํฉ๋๊ฐ ๋ฎ๊ณ ์ ์ฐ์ฑ์ด ์ข์ต๋๋ค.
Factory Method์ ์ฅ๋จ์
์ฅ์
- ํฌ๋ฆฌ์์ดํฐ์ ๊ตฌ์ ์ ํ๋ค์ด ๋จ๋จํ๊ฒ ๊ฒฐํฉ๋์ง ์๋๋ก ํ ์ ์์ต๋๋ค. ์ด๋ก ์ธํด ๊ธฐ๋ฅ ๊ฐ์ ์ ๊ธฐ๋ฅ์ ๋ณด์ํ๊ธฐ ์ํ ๋ฆฌํฉํ ๋ง ์์ ์ด ํธ๋ฆฌํฉ๋๋ค.
- ๋จ์ผ ์ฑ ์ ์์น. ์ ํ ์์ฑ ์ฝ๋๋ฅผ ํ๋ก๊ทธ๋จ์ ํ ์์น๋ก ์ด๋ํ์ฌ ์ฝ๋๋ฅผ ๋ ์ฝ๊ฒ ์ ์ง๊ด๋ฆฌํ ์ ์์ต๋๋ค.
- ๊ฐ๋ฐฉ/ํ์ ์์น. ๋น์ ์ ๊ธฐ์กด ํด๋ผ์ด์ธํธ ์ฝ๋๋ฅผ ํผ์ํ์ง ์๊ณ ์๋ก์ด ์ ํ์ ์ ํ๋ค์ ํ๋ก๊ทธ๋จ์ ๋์ ํ ์ ์์ต๋๋ค.
๋จ์
- ํจํด์ ๊ตฌํํ๊ธฐ ์ํด ๋ง์ ์๋ก์ด ์์ ํด๋์ค๋ค์ ๋์ ํด์ผ ํ๋ฏ๋ก ์ฝ๋๊ฐ ๋ ๋ณต์กํด์ง ์ ์์ต๋๋ค.
Factory Method๋ฅผ ์ฌ์ฉํ๋ ์ด์
ํฉํ ๋ฆฌ ๋ฉ์๋ ํจํด์ ์ฌ์ฉํ๋ ์ด์ ๋ ํด๋์ค์ ์์ฑ๊ณผ ์ฌ์ฉ์ ์ฒ๋ฆฌ๋ก์ง์ ๋ถ๋ฆฌํ์ฌ ์ฝ๋์ ๊ฒฐํฉ๋๋ฅผ ๋ฎ์ถ๊ธฐ ์ํจ์
๋๋ค.
๊ฒฐํฉ๋๋ ๊ฐ๋จํ ๋งํด์ ํด๋์ค์ ์ฒ๋ฆฌ ๋ก์ง์ ๋ํ ๋ณ๊ฒฝ์ ์ด ์๊ฒผ์ ๋ ์ผ๋ง๋ ์ฌ์ด๋ ์ดํํธ๋ฅผ ์ฃผ๋๊ฐ ์ธ๋ฐ,
ํฉํ ๋ฆฌ ๋ฉ์๋ ํจํด์ ์ฌ์ฉํ ๊ฒฝ์ฐ ์ง์ ๊ฐ์ฒด๋ฅผ ์์ฑํด ์ฌ์ฉํ๋ ๊ฒ์ ๋ฐฉ์งํ๊ณ ์๋ธ ํด๋์ค์ ์์ฑ ๋ก์ง์ ์์ํจ์ผ๋ก์จ ๋ณด๋ค ํจ์จ์ ์ธ ์ฝ๋ ์ ์ด๋ฅผ ํ ์ ์๊ณ ์์กด์ฑ์ ์ ๊ฑฐ ํฉ๋๋ค. ์ด๋ก ์ธํด ์ฝ๋๋ฅผ ๋์ฑ ์ฝ๊ฒ ์ ์ง๊ด๋ฆฌํ ์ ์์ต๋๋ค.
Factory Method ๊ตฌ์กฐ
Product
Factory method๊ฐ ์์ฑํ ๊ฐ์ฒด์ ์ธํฐํ์ด์ค๋ฅผ ์ ์ํฉ๋๋ค.
ConcreteProduct
Factory method๊ฐ ์์ฑํ ๊ฐ์ฒด๋ก, Product๋ฅผ implementsํฉ๋๋ค.
Creator
Product(ํน์ ConcreteProduct) ํ์
์ ๋ฐํํ๋ Factory method๋ฅผ ์ ์ํฉ๋๋ค.
Product ๊ฐ์ฒด๋ฅผ ๋ง๋ค๊ธฐ ์ํด factory method๋ฅผ ํธ์ถํ ์ ์์ต๋๋ค.
ConcreteCreator
ConcreteProduct์ ์ธ์คํด์ค๋ฅผ ๋ฐํํ๋ factory method๋ฅผ ์ค๋ฒ๋ผ์ด๋ฉํ์ฌ ๊ตฌํํฉ๋๋ค.
Sample Code: Java
๋ค์์ ๋๊ฐ์ง์ ์ฟ ํฐ(RewardCoupon, ReceiptCoupon)์ ๋ง๋๋ ํฉํ ๋ฆฌ๋ฉ์๋์ฟ ํฐ ์์ ์ ๋๋ค.
Product
public interface Coupon {
void name();
}
ConcreateProduct
class RewardCoupon implements Coupon {
public void name() {
System.out.println("Reward Coupon");
}
}
class ReceiptCoupon implements Coupon {
public void name() {
System.out.println("Receipt Coupon");
}
}
Creator
abstract class Factory {
public Coupon create(String couponCode) {
return this.createCoupon(couponCode);
}
abstract public Coupon createCoupon(String couponCode);
}
ConcreteCreator
class CouponFactory extends Factory {
public CouponFactory() {
System.out.println("CouponFactory ์์ฑ");
}
public Coupon createCoupon(String couponCode) {
if (model == "RewardCoupon") {
return new RewardCoupon();
} else {
return new ReceiptCoupon();
}
}
}
Main
public class Main {
public static void main(String[] args) {
Factory fac = new CouponFactory();
Coupon coupon = fac.create("RewardCoupon");
coupon.name();
coupon = fac.create("ReceiptCoupon");
coupon.name();
}
}
์ฐธ๊ณ :
https://refactoring.guru/ko/design-patterns/factory-method
Design Pattern, Strategy
Behavioral Object Pattern Strategy Pattern Define a family of algorithms, encapsulate each one, and make them interchangeable. Strategy lets the algorithm vary independently from clients that use it. - GoF Design Patterns ์ ๋ต ํจํด์ ๋์ผ ๊ณ์ด์
gngsn.tistory.com