🌻 JAVA/λ””μžμΈ νŒ¨ν„΄

4. νŒ©ν† λ¦¬(Factory) νŒ¨ν„΄ - Head First Design Patterns

iseunghan 2020. 4. 5. 16:38
λ°˜μ‘ν˜•

"new" λŠ” ꡬ상 객체λ₯Ό λœ»ν•œλ‹€.

μ•žμ—μ„œ 배운 것 처럼 κ΅¬μƒν΄λž˜μŠ€λ₯Ό λ°”νƒ•μœΌλ‘œ μ½”λ”©ν•˜λ©΄ λ‚˜μ€‘μ— μ½”λ“œλ₯Ό μˆ˜μ •ν•΄μ•Ό ν•  κ°€λŠ₯성이 높아지고, μœ μ—°μ„±μ΄ λ–¨μ–΄μ§€κ²Œ λœλ‹€.

 

Duck duck;

if( picnic) {
	duck = new MallardDuck();
} else if( hunting ){
	duck = new DecoyDuck();
} else if ( inBathTub){
 	duck = new RubberDuck();
}    

이런 μ½”λ“œλŠ” λ­”κ°€λ₯Ό λ°˜μ˜ν•˜κ±°λ‚˜, ν™•μž₯ν•΄μ•Ό ν• λ•Œ μ½”λ“œλ₯Ό λ‹€μ‹œ ν™•μΈν•˜κ³  μΆ”κ°€ λ˜λŠ” 제거 ν•΄μ•Ό ν•œλ‹€λŠ” 것을 λœ»ν•œλ‹€. λ”°λΌμ„œ 이런 μ½”λ“œλŠ” 관리 및 갱신이 νž˜λ“€μ–΄μ§€κ³  였λ₯˜κ°€ 생길 κ°€λŠ₯성이 크닀.

 

μ• ν”Œλ¦¬μΌ€μ΄μ…˜μ—μ„œ κ΅¬μƒν΄λž˜μŠ€μ˜ μΈμŠ€ν„΄μŠ€λ₯Ό λ§Œλ“œλŠ” 뢀뢄을 μ•„μ˜ˆ λ‹€λ₯Έμͺ½μœΌλ‘œ 뢄리 μ‹œμΌœμ•Ό ν•œλ‹€.

μ•žμ—μ„œ λ°°μ› λ˜ 원칙쀑 "λ°”λ€”μˆ˜ μžˆλŠ” 뢀뢄을 μ°Ύμ•„λ‚΄μ„œ λ°”λ€Œμ§€ μ•ŠλŠ” λΆ€λΆ„κ³Ό λΆ„λ¦¬μ‹œμΌœμ•Ό ν•œλ‹€." λ₯Ό λ§ν•œλ‹€.

 

 

 

κ°„λ‹¨ν•œ νŒ©ν† λ¦¬ 예제

public Pizza orderPizza( String type){
	Pizza pizza;
    
    if( type.equals("cheese")){
    	pizza = new CheesePizza();
    } else if( type.equals("greek")){
    	pizza = new GreekPizza();
    } else if( type.equals("peperoni")){
    	pizza = new PeperoniPizza();
    }
}

μœ„μ— μ½”λ“œ 쀑에 μΈμŠ€ν„΄μŠ€ 생성 뢀뢄을 뢄리 μ‹œν‚€λ©΄, μ•„λž˜μ™€ 같이 λœλ‹€.

public class SimplePizzaFactory{
	pubic Pizza createPizza(String type){
   	 	Pizza pizza = null;
    
   	 	if( type.equals("cheese")){
    		pizza = new CheesePizza();
   	 	} else if( type.equals("greek")){
   	 		pizza = new GreekPizza();
   	 	} else if( type.equals("peperoni")){
   	 		pizza = new PeperoniPizza();
   	 	}
    }
}

이런 μ‹μœΌλ‘œ λ°”λ€ŒλŠ” 뢀뢄을 λΆ„λ¦¬μ‹œν‚΄μœΌλ‘œμ¨ κ΅¬ν˜„μ„ λ³€κ²½ν•΄μ•Ό ν•˜λŠ” κ²½μš°μ— μ—¬κΈ°μ €κΈ° λ“€μ–΄κ°€μ„œ κ³ μΉ ν•„μš” 없이

νŒ©ν† λ¦¬ 클래슀만 λ³€κ²½ν•˜λ©΄ λœλ‹€.


νŒ©ν† λ¦¬ λ©”μ†Œλ“œ νŒ¨ν„΄

 

 

public abstract class PizzaStore{
	public Pizza orderPizza(String item){
    	Pizza pizza;
        
        pizza = createPizza(item);
        ...
        ..
        
        return pizza;
    }
    abstract Pizza createPizza(String item); //νŒ©ν† λ¦¬ κΈ°λŠ₯을 ν•˜λŠ” λ©”μ†Œλ“œ!!
}
public class NYPizzaStore extends PizzaStore {

	Pizza createPizza(String item) { // μΈμŠ€ν„΄μŠ€ 생성을 μ±…μž„μ§€λŠ” νŒ©ν† λ¦¬ λ©”μ†Œλ“œ**
		if (item.equals("cheese")) {
			return new NYStyleCheesePizza();
		} else if (item.equals("veggie")) {
			return new NYStyleVeggiePizza();
		} else if (item.equals("clam")) {
			return new NYStyleClamPizza();
		} else if (item.equals("pepperoni")) {
			return new NYStylePepperoniPizza();
		} else return null;
	}
}

슈퍼 클래슀의 orederPizza() λ©”μ†Œλ“œμ—μ„œ μ–΄λ–€ ν”Όμžκ°€ μ–΄λ–»κ²Œ λ§Œλ“€μ–΄μ§€λŠ”μ§€ λͺ¨λ₯Έλ‹€.

μ„œλΈŒ 클래슀의 createPizza() λ©”μ†Œλ“œκ°€ 결정을 ν•˜κ²Œ λœλ‹€. -> νŒ©ν† λ¦¬ λ©”μ†Œλ“œμ˜ μž₯점.

 

abstract Product factoryMethod ( String type )

항상 abstract둜 μ„ μ–Έν•΄μ„œ μ„œλΈŒ ν΄λž˜μŠ€μ—μ„œ 객체생성을 μ±…μž„μ§€λ„λ‘ ν•΄μ•Όν•œλ‹€.

 

* μž₯점) νŒ©ν† λ¦¬λ©”μ†Œλ“œλŠ” 객체 생성을 μ²˜λ¦¬ν•˜λ©°, νŒ©ν† λ¦¬ λ©”μ†Œλ“œλ₯Ό μ΄μš©ν•˜λ©΄

객체λ₯Ό μƒμ„±ν•˜λŠ” μž‘μ—…μ„ μ„œλΈŒν΄λž˜μŠ€μ— μΊ‘μŠν™” μ‹œν‚¬μˆ˜ μžˆλ‹€.

 

μ΄λ ‡κ²Œ ν•˜λ©΄ μŠˆνΌν΄λž˜μŠ€μ— μžˆλŠ” ν΄λΌμ΄μ–ΈνŠΈ μ½”λ“œμ™€ μ„œλΈŒν΄λž˜μŠ€μ— μžˆλŠ” 객체 μƒμ„±μ½”λ“œλ₯Ό 뢄리 μ‹œν‚¬μˆ˜ μžˆλ‹€.

 

public abstract class Pizza {
	String name;
	String dough;
	String sauce;
	ArrayList<String> toppings = new ArrayList<String>();
 
	void prepare() {
		System.out.println("Prepare " + name);
		System.out.println("Tossing dough...");
		System.out.println("Adding sauce...");
		System.out.println("Adding toppings: ");
		for (String topping : toppings) {
			System.out.println("   " + topping);
		}
	}
  
	void bake() {
		System.out.println("Bake for 25 minutes at 350");
	}
 
	void cut() {
		System.out.println("Cut the pizza into diagonal slices");
	}
  
	void box() {
		System.out.println("Place pizza in official PizzaStore box");
	}
 
	public String getName() {
		return name;
	}
}
public class NYStyleCheesePizza extends Pizza {

	public NYStyleCheesePizza() { 
		name = "NY Style Sauce and Cheese Pizza";
		dough = "Thin Crust Dough";
		sauce = "Marinara Sauce";
 
		toppings.add("Grated Reggiano Cheese");
	}
}
//main

PizzaStore nyStore = new NYPizzaStore();
Pizza pizza = nyStore.orderPizza("cheese");
System.out.prinltn("Ethan ordered a " + pizza.getName() );

좜λ ₯)

--- Making a NY Style Sauce and Cheese Pizza ---
Prepare NY Style Sauce and Cheese Pizza
Tossing dough...
Adding sauce...
Adding toppings: 
   Grated Reggiano Cheese
Bake for 25 minutes at 350
Cut the pizza into diagonal slices
Place pizza in official PizzaStore box
Ethan ordered a NY Style Sauce and Cheese Pizza

 

 

Pizza νŒ©ν† λ¦¬ λ©”μ†Œλ“œ νŒ¨ν„΄μ„ μ μš©ν•œ 클래슀 λ‹€μ΄μ–΄κ·Έλž¨

νŒ©ν† λ¦¬ λ©”μ†Œλ“œ νŒ¨ν„΄ μ •μ˜ ) νŒ©ν† λ¦¬ λ©”μ†Œλ“œ νŒ¨ν„΄μ—μ„œλŠ” 객체λ₯Ό μƒμ„±ν•˜κΈ° μœ„ν•œ μΈν„°νŽ˜μ΄μŠ€λ₯Ό μ •μ˜ν•˜λŠ”λ°,

μ–΄λ–€ 클래슀의 μΈμŠ€ν„΄μŠ€λ₯Ό λ§Œλ“€μ§€λŠ” μ„œλΈŒν΄λž˜μŠ€μ—μ„œ κ²°μ •ν•˜κ²Œ λ§Œλ“ λ‹€.

νŒ©ν† λ¦¬ λ©”μ†Œλ“œ νŒ¨ν„΄μ„ μ΄μš©ν•˜λ©΄ 클래슀의 μΈμŠ€ν„΄μŠ€λ₯Ό λ§Œλ“œλŠ” 일을 μ„œλΈŒν΄λž˜μŠ€μ—κ²Œ 맑긴닀.

 

 

 

μ˜μ‘΄μ„± 뒀집기 원칙 ) μΆ”μƒν™”λœ 것에 μ˜μ‘΄ν•˜κ²Œ λ§Œλ“€μ–΄λΌ. ꡬ상 ν΄λž˜μŠ€μ— μ˜μ‘΄ν•˜λ„λ‘ λ§Œλ“€μ§€ 마라.

 

 

μœ„μ— 클래슀 λ‹€μ΄μ–΄κ·Έλž¨μ—μ„œ PizzaStore 와 Pizza , μ €μˆ˜μ€€κ΅¬μ„±μš”μ†ŒμΈ pizza객체듀 관계λ₯Ό μ‚΄νŽ΄λ³΄λ©΄

PizzaStore -> Pizza <- pizza ( ex. NYStyleCheesePizza ...etc)

이렇듯 λͺ¨λ‘ μΆ”μƒν΄λž˜μŠ€μΈ Pizzaμ—λ§Œ μ˜μ‘΄ν•˜λŠ”κ²ƒμ΄ 보인닀.

νŒ©ν† λ¦¬ λ©”μ†Œλ“œ νŒ¨ν„΄μœΌλ‘œ 인해 μ˜μ‘΄μ„± 뒀집기 원칙을 적용된 것이닀.

 

PizzaStoreμ—λŠ” Pizza객체만 있고, μ €μˆ˜μ€€κ΅¬μ„±μš”μ†Œ pizza객체듀은

λͺ¨λ‘ μ„œλΈŒν΄λž˜μŠ€μ—μ„œ κ²°μ •ν•˜κΈ° λ•Œλ¬Έμ— 이런 관계가 λ‚˜μ˜¬μˆ˜ μžˆλŠ” 것이닀.

 


 

좔상 νŒ©ν† λ¦¬ νŒ¨ν„΄

 

 

 

public interface PizzaIngredientFactory {
 
	public Dough createDough();
	public Sauce createSauce();
	public Cheese createCheese();
	public Veggies[] createVeggies();
	public Pepperoni createPepperoni();
	public Clams createClam();
}
public class NYPizzaIngredientFactory implements PizzaIngredientFactory {
 
	public Dough createDough() {
		return new ThinCrustDough();
	}
 
	public Sauce createSauce() {
		return new MarinaraSauce();
	}
 
	public Cheese createCheese() {
		return new ReggianoCheese();
	}
 
	public Veggies[] createVeggies() {
		Veggies veggies[] = { new Garlic(), new Onion(), new Mushroom(), new RedPepper() };
		return veggies;
	}
 
	public Pepperoni createPepperoni() {
		return new SlicedPepperoni();
	}

	public Clams createClam() {
		return new FreshClams();
	}
}
public abstract class Pizza {
	String name;

	Dough dough;
	Sauce sauce;
	Veggies veggies[];
	Cheese cheese;
	Pepperoni pepperoni;
	Clams clam;

	abstract void prepare();
	...
    ..
 }
public class CheesePizza extends Pizza {
	PizzaIngredientFactory ingredientFactory;
 
	public CheesePizza(PizzaIngredientFactory ingredientFactory) {
		this.ingredientFactory = ingredientFactory;
	}
 
	void prepare() {
		System.out.println("Preparing " + name);
		dough = ingredientFactory.createDough();
		sauce = ingredientFactory.createSauce();
		cheese = ingredientFactory.createCheese();
	}
}
public class CheesePizza extends Pizza {
	PizzaIngredientFactory ingredientFactory;
 
	public CheesePizza(PizzaIngredientFactory ingredientFactory) {
		this.ingredientFactory = ingredientFactory;
	}
 
	void prepare() {
		System.out.println("Preparing " + name);
		dough = ingredientFactory.createDough();
		sauce = ingredientFactory.createSauce();
		cheese = ingredientFactory.createCheese();
	}
}

 

좔상 νŒ©ν† λ¦¬ νŒ¨ν„΄ : 클래슀 λ‹€μ΄μ–΄κ·Έλž¨ (λ‚˜λ¨Έμ§€ ν΄λž˜μŠ€ μƒλž΅)

 

 

 

좔상 νŒ©ν† λ¦¬ νŒ¨ν„΄ ) 좔상 νŒ©ν† λ¦¬ νŒ¨ν„΄μ—μ„œλŠ” μΈν„°νŽ˜μ΄μŠ€λ₯Ό μ΄μš©ν•˜μ—¬ μ„œλ‘œ μ—°κ΄€λœ,

λ˜λŠ” μ˜μ‘΄ν•˜λŠ” 객체λ₯Ό ꡬ상 클래슀λ₯Ό μ§€μ •ν•˜μ§€ μ•Šκ³ λ„ 생성할 수 μžˆμŠ΅λ‹ˆλ‹€.

 

λ”°λΌμ„œ ν΄λΌμ΄μ–ΈνŠΈμ™€ νŒ©ν† λ¦¬μ—μ„œ μƒμ‚°λ˜λŠ” μ œν’ˆμ„ λΆ„λ¦¬μ‹œν‚¬ 수 μžˆλ‹€.

 

 

 

 

λ°˜μ‘ν˜•