팩토리 패턴(Factory Pattern)
디자인패턴 2014. 11. 11. 14:221. 팩토리 패턴이란?
팩토리는 구상(Concrete) 클래스가 아닌 추상(Abstract) 클래스/인터페이스에 맞춰서 코딩할 수 있게 해 주는 강력한 기법이다. 모든 팩토리 패턴에서는 애플리케이션의 구상(Concrete) 클래스에 대한 의존성을 줄여줌으로써 느슨한 결합(Loose Coupling)을 도와준다. 그리고 객체 생성을 캡슐화(Encapsulation)할 수 있다.
(1) 팩토리 메소드 패턴
팩토리 메소드 패턴은 클라이언트 코드와 Instance를 만들어야 할 구상(Concrete) 클래스를 분리시켜야 할 때 사용한다. 또한 어떤 구상(Concrete) 클래스를 필요로 하게 될지 미리 알 수 없는 경우에도 매우 유용하다.
팩토리 메소드 패턴에서는 객체를 생성하기 위한 인터페이스를 만들고, 어떤 클래스의 Instance를 만들지는 Subclass에게 위임(Delegate)한다. Subclass에서는 팩토리 메소드를 구현하여 객체를 생성한다.
(2) 추상(Abstract) 팩토리 패턴
추상(Abstract) 팩토리 패턴은 클라이언트에서 구상(Concrete) 클래스에 직접 의존하지 않고도 서로 연관된 일련의 제품들(제품군)을 만들어야 할 때 사용한다.
추상(Abstract) 팩토리 패턴에서는 객체 구성(Composition)을 활용한다. 객체 생성이 팩토리 인터페이스에서 선언한 메소드들에서 구현된다.
2. 팩토리 패턴 예시
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 | // 추상(Abstract) 팩토리 // 추상(Abstract) 팩토리를 통해서 제품군(원재료들)을 생성하기 위한 인터페이스를 제공할 수 있다. // 각 Subclass에서는 지역별 사정에 맞는 재료들을 구현한다. public interface PizzaIngredientFactory { // 추상(Abstract) 팩토리에서 제품을 생산하기 위한 메소드를 팩토리 메소드 패턴으로 구현하는 경우가 있다. public Dough createDough(); public Sauce createSauce(); public Cheese createCheese(); public Veggies[] createVeggies(); public Pepperoni createPepperoni(); public Clams createClam(); } public class NYPizzaIngredientFactory implements PizzaIngredientFactory { @Override public Dough createDough() { return new ThinCrustDough(); } @Override public Sauce createSauce() { return new MarinaraSauce(); } @Override public Cheese createCheese() { return new ReggianoCheese(); } @Override public Veggies[] createVeggies() { Veggies veggies[] = { new Garlic(), new Onion(), new Mushroom(), new RedPepper() }; return veggies; } @Override public Pepperoni createPepperoni() { return new SlicedPepperoni(); } @Override public Clams createClam() { return new FreshClams(); } } public class ChicagoPizzaIngredientFactory implements PizzaIngredientFactory { @Override public Dough createDough() { return new ThickCrustDough(); } @Override public Sauce createSauce() { return new PlumTomatoSauce(); } @Override public Cheese createCheese() { return new Mozzarella(); } @Override public Veggies[] createVeggies() { Veggies veggies[] = { new EggPlant(), new Spinach(), new BlackOlives() }; return veggies; } @Override public Pepperoni createPepperoni() { return new SlicedPepperoni(); } @Override public Clams createClam() { return new FrozenClam(); } } import java.util.*; public abstract class Pizza { String name; String dough; String sauce; Veggies veggies[]; Cheese cheese; Pepperoni pepperoni; Clams clam; // 피자를 만드는 데 필요한 재료들을 정돈 // 피자에는 여러 종류가 있고, 지역마다 사용하는 재료가 다르므로 팩토리 메소드를 사용함. abstract void prepare(); void bake() { System.out.println( "Bake for 25 minutes at 350" ); } void cut() { System.out.println( "Cutting the pizza into diagonal slices" ); } void box() { System.out.println( "Place pizza in oficial PizzaStore box" ); } public String getName() { return name; } public void setName(String name) { this .name = name; } } public class CheesePizza extends Pizza { PizzaIngredientFactory ingredientFactory; public CheesePizza(PizzaIngredientFactory ingredientFactory) { this .ingredientFactory = ingredientFactory; } @Override void prepare() { System.out.println( "Preparing " + name); // 사용하는 재료에 따라 피자 종류가 달라진다. 그래서 IngredientFactory에 따라 피자가 다양하게 만들어질 수 있다. dough = ingredientFactory.createDough(); cheese = ingredientFactory.createCheese(); sauce = ingredientFactory.createSauce(); } } public class ClamPizza extends Pizza { PizzaIngredientFactory ingredientFactory; public ClamPizza(PizzaIngredientFactory ingredientFactory) { this .ingredientFactory = ingredientFactory; } @Override void prepare() { System.out.println( "Preparing " + name); dough = ingredientFactory.createDough(); sauce = ingredientFactory.createSauce(); cheese = ingredientFactory.createCheese(); clam = ingredientFactory.createClam(); } } public abstract class PizzaStore { public Pizza orderPizza(String type){ Pizza pizza; // createPizza 메소드를 호출하면 PizzaStore를 구현한 Subclass에서 처리가 된다. // Pizza 객체의 Instance를 만드는 일은 PizzaStore의 Subclass에 있는 createPizza() 메소드에서 처리한다. // 실제로 어떤 구상(Concrete) 클래스에서 작업을 처리되고 있는지 알 수 없기 때문에, PizzaStore와 Pizza 클래스는 서로 분리되어 있다고 할 수 있다. pizza = createPizza(type); pizza.prepare(); pizza.bake(); pizza.cut(); pizza.box(); return pizza; } // 팩토리 메소드는 클라이언트(Superclass에 있는 orderPizza()와 같은 코드)에서 실제로 생성되는 Concrete 객체(Pizza 객체)가 무엇인지 알 수 없게 만드는 역할도 한다. protected abstract Pizza createPizza(String type); } public class NYPizzaStore extends PizzaStore { @Override protected Pizza createPizza(String item) { Pizza pizza = null ; PizzaIngredientFactory ingredientFactory = new NYPizzaIngredientFactory(); if (item.equals( "cheese" )) { pizza = new CheesePizza(ingredientFactory); pizza.setName( "New York Style Cheese Pizza" ); } else if (item.equals( "veggie" )) { pizza = new VeggiePizza(ingredientFactory); pizza.setName( "New York Style Veggie Pizza" ); } else if (item.equals( "clam" )) { pizza = new ClamPizza(ingredientFactory); pizza.setName( "New York Style Clam Pizza" ); } else if (item.equals( "pepperoni" )) { pizza = new PepperoniPizza(ingredientFactory); pizza.setName( "New York Style Pepperoni Pizza" ); } return pizza; } } public class ChicagoPizzaStore extends PizzaStore { @Override protected Pizza createPizza(String item) { Pizza pizza = null ; PizzaIngredientFactory ingredientFactory = new ChicagoPizzaIngredientFactory(); if (item.equals( "cheese" )) { pizza = new CheesePizza(ingredientFactory); pizza.setName( "Chicago Style Cheese Pizza" ); } else if (item.equals( "veggie" )) { pizza = new VeggiePizza(ingredientFactory); pizza.setName( "Chicago Style Veggie Pizza" ); } else if (item.equals( "clam" )) { pizza = new ClamPizza(ingredientFactory); pizza.setName( "Chicago Style Clam Pizza" ); } else if (item.equals( "pepperoni" )) { pizza = new PepperoniPizza(ingredientFactory); pizza.setName( "Chicago Style Pepperoni Pizza" ); } return pizza; } } public class PizzaTestDrive { /** * @param args */ public static void main(String[] args) { PizzaStore nyStore = new NYPizzaStore(); PizzaStore chicagoStore = new ChicagoPizzaStore(); Pizza pizza = nyStore.orderPizza( "cheese" ); System.out.println( "Ethan ordered a " + pizza.getName() + "\n" ); pizza = chicagoStore.orderPizza( "cheese" ); System.out.println( "Joel ordered a " + pizza.getName() + "\n" ); } } |
참고
Head FIrst Design Pattern : 스토리가 있는 패턴 학습법
http://www.gurubee.net/pages/viewpage.action?pageId=1507401
출처 - http://digitanomad.blogspot.kr/2013/02/1.html
'디자인패턴' 카테고리의 다른 글
커맨드 패턴(Command Pattern) (0) | 2014.11.11 |
---|---|
싱글턴 패턴(Singleton Pattern) (0) | 2014.11.11 |
옵저버 패턴(Observer Pattern) (0) | 2014.11.11 |
데코레이터 패턴(Decorator Pattern) (0) | 2014.11.11 |
어댑터 패턴(Adapter Pattern) (0) | 2014.11.11 |