디자인 패턴은 소프트웨어 설계 시 특정 상황에서 자주 만나는 문제를 해결하기 위해 사용할 수 있는 재사용 가능한 솔루션을 말한다.
출처 - 토비의 스프링 3
컴퓨터 과학에서의 디자인 패턴
소프트웨어 개발 방법에서 사용되는 디자인 패턴은, 프로그램 개발에서 자주 나타나는 과제를 해결하기 위한 방법 중 하나로, 과거의 소프트웨어 개발 과정에서 발견된 설계의 노하우를 축적하여 이름을 붙여, 이후에 재이용하기 좋은 형태로 특정의 규약을 묶어서 정리한 것이다. 알고리즘과 같이 프로그램 코드로 바로 변환될 수 있는 형태는 아니지만, 특정한 상황에서 구조적인 문제를 해결하는 방식을 설명해 준다.
이 용어를 소프트웨어 개발 영역에서 구체적으로 처음 제시한 곳은, GoF(Gang of Four)라 불리는 네명의 컴퓨터 과학 연구자들이 쓴 서적 'Design Patterns: Elements of Reusable Object-Oriented Software'(재이용 가능한 객체지향 소프트웨어의 요소 - 디자인 패턴)이다. GoF는 컴퓨터 소프트웨어 공학 분야의 연구자인 에릭 감마, 리차드 헬름, 랄프 존슨, 존 블리시디스의 네명을 지칭한다.
[편집]디자인 패턴과 패턴 학회
GoF의 디자인 패턴과 그 멤버들 그리고 패턴에 관심을 갖는 학자, 엔지니어, 출판업자들이 모여서 PLoP라는 학회를 시작하게 된다. 1994년부터 시작된 학회는 2012년 현재까지 미국에서 각 주를 돌아가며, 전 세계의 패턴 저자 및 학습자들을 불러 새로운 패턴, 패턴언어, Agile등에 대해서 토의한다. 2010년도부터 AsianPLoP와 기타 Licensing된 미국밖 세계 PLoP움직임으로 퍼져나가고 있다. 한국에서도 KPLoP로 패턴저자인 손영수님과 그가 리딩하는 스터디 그룹인 EVA가 주축이 되어, 주요 국내 커뮤니티 행사등에서 패턴을 전도하고 있다.
팩토리 메서드 패턴(Factory method pattern)은 객체지향 디자인 패턴이다. 다른 생성 패턴들처럼, 이 패턴도 생성하려는 객체의 클래스를 정확히 지정하지 않으면서 객체를 만드는 문제를 다룬다. 팩토리 메서드 패턴은 이 문제를 객체를 만드는 또 다른 메서드를 정의하여 처리한다. 일반적으로, 팩토리 메서드라는 용어는 객체를 만드는 것이 주 목적인 메서드를 지칭하는데 주로 사용한다.
목차[숨기기] |
[편집]예
[편집]C#
Pizza example:
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."); } } public class HamAndMushroomPizza : Pizza { private decimal price = 8.5M; public override decimal GetPrice() { return price; } } public class DeluxePizza : Pizza { private decimal price = 10.5M; public override decimal GetPrice() { return price; } } public class SeafoodPizza : Pizza { private decimal price = 11.5M; public override decimal GetPrice() { return price; } } // Somewhere in the code ... Console.WriteLine( Pizza.PizzaFactory(Pizza.PizzaType.Seafood).GetPrice().ToString("C2") ); // $11.50 ...
[편집]자바스크립트
Pizza example:
//Our pizzas function HamAndMushroomPizza(){ var price = 8.50; this.getPrice = function(){ return price; } } function DeluxePizza(){ var price = 10.50; this.getPrice = function(){ return price; } } function SeafoodPizza(){ var price = 11.50; this.getPrice = function(){ return price; } } //Pizza Factory function PizzaFactory(){ this.createPizza = function(type){ switch(type){ case "Ham and Mushroom": return new HamAndMushroomPizza(); case "DeluxePizza": return new DeluxePizza(); case "Seafood Pizza": return new SeafoodPizza(); default: return new DeluxePizza(); } } } //Usage var pizzaPrice = new PizzaFactory().createPizza("Ham and Mushroom").getPrice(); alert(pizzaPrice);
[편집]루비
Pizza example:
class HamAndMushroomPizza def price 8.50 end end class DeluxePizza def price 10.50 end end class SeafoodPizza def price 11.50 end end class PizzaFactory def create_pizza(style='') case style when 'Ham and Mushroom' HamAndMushroomPizza.new when 'DeluxePizza' DeluxePizza.new when 'Seafood Pizza' SeafoodPizza.new else DeluxePizza.new end end end # usage factory = PizzaFactory.new pizza = factory.create_pizza('Ham and Mushroom') pizza.price #=> 8.5 # bonus formatting formatted_price = sprintf("$%.2f", pizza.price) #=> "$8.50" # one liner sprintf("$%.2f", PizzaFactory.new.create_pizza('Ham and Mushroom').price) #=> "$8.50"
[편집]파이썬
# Our Pizzas class Pizza: HAM_MUSHROOM_PIZZA_TYPE = 0 DELUXE_PIZZA_TYPE = 1 SEAFOOD_PIZZA_TYPE= 2 def __init__(self): self.__price = None def getPrice(self): return self.__price class HamAndMushroomPizza(Pizza): def __init__(self): self.__price = 8.50 class DeluxePizza(Pizza): def __init__(self): self.__price = 10.50 class SeafoodPizza(Pizza): def __init__(self): self.__price = 11.50 class PizzaFactory: def createPizza(self, pizzaType): if pizzaType == Pizza.HAM_MUSHROOM_PIZZA_TYPE: return HamAndMushroomPizza() elif pizzaType == Pizza.DELUXE_PIZZA_TYPE: return DeluxePizza() elif pizzaype == Pizza.SEAFOOD_PIZZA_TYPE: return SeafoodPizza() else: return DeluxePizza() # Usage pizzaPrice = PizzaFactory().createPizza(Pizza.HAM_MUSHROOM_PIZZA_TYPE).getPrice() print "$%.02f" % pizzaPrice
Factory Method 패턴 (팩토리 메소드 패턴) [1] 은 GoF (Gang of Four; 4 명의 갱단들)에 의해 정의된 디자인 패턴 중 하나이다. Factory Method 패턴은 다른 클래스의 생성자를 서브 클래스에서 덮어쓸 수있는 자신의 메서드로 대체하여 응용 프로그램에 전문화된 객체의 생성을 서브 클래스로 내몰고, 클래스의 재사용성을 높이는 것을 목적으로한다.
Virtual Constructor 패턴이라고도 불리는 [1] .
목차[ 숨기기 ] |
클래스 다이어그램 [ 편집 ]
Factory Method 패턴의 클래스 다이어그램 은 다음과 같다.
여기서 anOperation은 factoryMethod를 호출 Product 서브 클래스의 인스턴스를 얻고 이용한다. factoryMethod 같은 메소드는 factory method했다.
factoryMethod 기본 동작을 포함한 구체적인 방법이 될 수있다. 매개 변수를 그것에 의해 생성하는 클래스를 바꿀 수도있다. ConcreteCreator마다 작업 방법을 Product로 다른 클래스에 제공하는 케이스는 factoryMethod를 public으로 공개한다. [1] . 그러나 factoryMethod는 덮어 쓰지 가정이기 때문에 private로하지 않는다.
사용 예제 [ 편집 ]
예를 들어, Java List의 요소를 다양한 정렬하는 프로그램을 생각한다. 이 소스 코드는 J2SE 1.5 이상 버전에서 작동한다.
import java.util.ArrayList ; import java.util.Arrays ; import java.util.Collections ; import java.util.Comparator ; import java.util.List ; / / Creator에 해당하는 abstract class ListPrinter { / / anOperaton에 해당하는 public void printList ( List < String > list ) { Comparator < String > comparator = createComparator ( ) ; list = New ArrayList < String > ( list ) ; Collections . sort ( list, comparator ) ; for ( String Item : list ) { System . out . println ( item ) ; } } / / factoryMethod에 해당하는 protected abstract Comparator < String > createComparator ( ) ; } / / ConcreteCreator에 해당하는 class DictionaryOrderListPrinter extends ListPrinter { @ Override protected Comparator < String > createComparator ( ) { return New DictionaryOrderComparator ( ) ; } } / / java.util.Comparator가 Product에 해당하는 / / ConcreteProduct에 해당하는 class DictionaryOrderComparator Implements Comparator < String > { @ Override public int Compare ( String str1, String str2 ) { return str1. compareTo ( str2 ) ; } } / / ConcreteCreator에 해당하는 class LengthOrderListPrinter extends ListPrinter { @ Override protected Comparator < String > createComparator ( ) { return New LengthOrderComparator ( ) ; } } / / ConcreteProduct에 해당하는 class LengthOrderComparator Implements Comparator < String > { public int Compare ( String str1, String str2 ) { return str1. length ( ) - str2. length ( ) ; } } / / 기본 클래스 public class FactoryMethodSample { public static void Main ( String args [ ] ) { List < String > list = Arrays . asList ( "딸기" , "모모" , "무화과" ) ; System . out . println ( "가나다 순으로보기 :" ) ; New DictionaryOrderListPrinter ( ) . printList ( list ) ; System . out . println ( ) ; System . out . println ( "길이 순으로보기 :" ) ; New LengthOrderListPrinter ( ) . printList ( list ) ; } }
이 프로그램은 다음과 같은 결과를 출력한다.
가나다 순으로보기 : 딸기 무화과 모모 길이 정렬 : 모모 딸기 무화과
상반기에 목록을 사전 순으로 표시하여 나중에 목록을 문자열 길이 순으로 표시하고있다. 목록을 정렬 바꾸어보기 ListPrinter # printList 메서드는 정렬 바꾸어 사용 Comparator를 생성할 때 new 연산자를 사용하여 직접 생성하는 것이 아니라 추상 메서드 createComparator를 사용하여 서브 클래스 생성을 맡긴다.
관련된 패턴 [ 편집 ]
factory method는 보통 template method ( Template Method 패턴 참조)이다 anOperation 호출된다. 그러나 factory method를 public으로 다른 클래스에서 부르는 경우도있다 [1] .
Abstract Factory 패턴 의 AbstractFactory 클래스는 factory method를 가지고 그것을 개별 서브 클래스가 재정 생성하는 Product를 바꾸는 수법이 일반적이다. 하지만 Prototype 패턴 을 사용하여 prototype과 객체의 변경에 의해 생성하는 Product를 바꾸는 방법도있다 [1] .
Abstract Factory 패턴의 차이 [ 편집 ]
"객체 지향의 재사용을위한 디자인 패턴"에서는 Factory Method 패턴은 "클래스 패턴 '으로 분류되고있다. 반면 Abstract Factory 패턴은 "개체 패턴 '으로 분류되고있다.
Factory Method 패턴은 부모 클래스인 Creator 클래스가 자식 클래스이다 ConcreteCreator 클래스 객체의 생성을 맡긴다는, Creator 클래스와 ConcreteCreator 클래스와 관련이있다. 한편 Abstract Factory 패턴은 Client의 인스턴스가 ConcreteFactory의 인스턴스에 객체 생성을 맡긴다는 오브젝트 간의 관련이다.
관련 항목 [ 편집 ]
참고 문헌 [ 편집 ]
'Framework & Platform > Common' 카테고리의 다른 글
모델1과 모델2의 차이점 (0) | 2012.03.21 |
---|---|
log4j.properties (0) | 2012.03.19 |
Refactoring (0) | 2012.03.18 |
Struts 2 따라잡기 (0) | 2010.12.26 |
MVC(Model , View , Controller) (0) | 2010.11.28 |