The Abstract Factory Pattern

추상화 팩토리 패턴은 팩토리 패턴보다 더 추상화한 단계이다. 이 패턴은 연관된 객체의 여러 클래스들 중의 하나를 반환하고자 할 때 사용할 수 있다. 즉, 추상화 팩토리는 여러 팩토리들 중의 하나를 반환하는 팩토리 객체이다.

    추상화 팩토리의 고전적인 응용중의 하나는 컴퓨터시스템이 다중의 "룩앤필(look-and-feel)"을 지원하는 경우에서의 사용이다. 여기서 팩토리는 사용하는 시스템이 windows이면 windows를 반환하는 객체이다.

    자바에서는 룩앤필을 지원하는데 그 사용예를 잠깐 살펴보자.
 
String laf = UIManager.getSystemLookAndFeelClassName();
try {
	UIManager.setLookAndFeel(laf);
}
catch (UnsupportedLookAndFeelException exc) {
	System.err.println("UnsupportedL&F: " + laf);
}
catch (Exception exc) {
	System.out.println("Error loading " + laf);
}

A GardenMaker Factory

    응용단계에서 사용하고자 하는 추상화 팩토리의 간단한 예를 고려해 보자. 

  정원의 배치에 관련된 프로그램을 작성한다고 하자.
정원은 일년생 식물의 정원일 수 있고, 야채를 가꾸는 정원일 수 있고, 다년생의 식물들이 사는 정원일 수 도 있다.
그러나, 우리가 계획하는 정원의 종류와는 상관없이 다음과 같은 사항들에 대해 고려하게 될 것이다.

1. 가장자리에는 어떤 식물을 심는 것이 좋을 것인가?
2. 중앙에는 어떤 식물들이 좋을 것인가?
3. 응달진 부분에는 어떤 식물들이 좋을 것인가?

    ... 이외에도 많은 요구 사항들이 있겠지만, 우리의 예에서는 생략할 것이다. 

Garden 클래스는 이러한 요구들에 대한 기본 클래스이다.
 
public abstract class Garden {
	public abstract Plant getCenter();
	public abstract Plant getBorder();
	public abstract Plant getShade();
}
현실 세계에서는 보다 정교하게 식물의 정보를 이용하여 정원의 형태를 다루겠지만, 우리의 예에서는 간단히 식물의 종류 중 하나를 반환할 것이다. 예를 들어 Vegertable garden은 다음과 같이 작성할 수 있다.
 
public class VegieGarden extends Garden {
	public Plant getShade() {
		return new Plant("Broccoli");
	}
	public Plant getCenter() {
		return new Plant("Corn");
	}
	public Plant getBorder() {
		return new Plant("Peas");
	}
}
이제 우리는 일련의 Garden 객체들을 가지고 있으며, 각각의 객체들은 여러개의 Plant 객체중 하나를 반환하게 된다. 이제 우리는 인자로 문자열이 주어졌을 때 Gadend 객체중 하나를 반환하는 추상화 팩토리를 생성할 수 있다.
 
class GardenMaker {
//Abstract Factory which returns one of three gardens
	private Garden gd;
	
	public Garden getGarden(String gtype) {
		gd = new VegieGarden();	//default 
		if(gtype.equals("Perennial"))
			gd=new PerennialGarden();
		if(gtype.equals("Annual"))
			gd=new AnnualGarden();
		
		return gd;
	}
}
이 간단한 팩토리 시스템은 아래의 그림처럼 다소 복잡한 사용자 인터페이스를 이용하여 작동되어질 수 있다.

            ##########0*

How the User Interface Works

     이 간단한 인터페이스는 두개의 부분으로 구성되어 있다. 좌측은 Garden 타입을 결정하는 라디오버튼으로 구성되어 있고, 우측은 식물의 카테고리를 결정할 수 있도록 버튼으로 구성되어 있다. Garden 타입 중 하나를 선택하였을 때, Garden 팩토리를 작동 시킨다. 이 것은 라디오버튼의 캡션에 의하여 Garden의 타입을 반환한다.
 
public void itemStateChanged(ItemEvent e) {
	JRadioButton rd = (JRadioButton)e.getSource();
	
	//get a garden type based on label of radio button
	garden = new GardenMaker().getGarden(rd.getLabel());
	
	//Clear names of plants in display
	shadePlant="";
	centerPlant="";
	borderPlant="";
	
	gardenPlot.repaint();	//display empty garden
}
그리고 나서 사용자가 식물 타입 버튼 중의 하나를 누르면, 식물의 타입은 반환되고, 식물의 이름이 나타난다.
 
public void actionPerformed(ActionEvent e) {
	Object obj = e.getSource();
	if(obj==centerBTN)
		setCenter();
	if(obj==borderBTN)
		setBord();
	if(obj==shadeBTN)
		setShade();
}

//----------------------------------------------------------

private void setCenter() {
	if(garden!=null)
		centerPlant = garden.getCenter().getName();
	gardenPlot.repaint();
}

private void setBord() {
	if(garden!=null)
		borderPlant = garden.getBorder().getName();
	gardenPlot.repaint();
}

private void setShade() {
	if(garden!=null)
		shadePlant = garden.getShade().getName();
	gardenPlot.repaint();
}	
식물의 이름들은 GardenPanel에서 표시되며, 각 이름들은 그려진다.
 
class GardenPanel extends JPanel {                            
	public GardenPanel(){                                 
		super();			              
		setBackground(Color.white);                   
		setBorder(LineBorder.createBlackLineBorder());
	}                                                     
	                                                      
	public void paintComponent(Graphics g) {              
		super.paintComponent(g);                      
		                                              
		//draw tree shadow                            
		g.setColor(Color.lightGray);                  
		g.fillArc(0,0,80,80,0,360);                   
		                                              
		//draw plants names                           
		g.setColor(Color.black);                      
		g.drawString(centerPlant, 100, 100);          
		g.drawString(borderPlant, 75, 180);           
		g.drawString(shadePlant, 10, 40);             
	}                                                     
}                                                               

Consequences of Abstract Factory

추상화 팩토리의 주요 목적 중의 하나는 생성된 구체적인 클래스들을 고립시키는 것이다. 이러한 클래스들의 실제적인 이름은 팩토리에 숨겨져 있고 클라이언트 단계에서 전혀 알려질 필요가 없다. 

    클래스들의 고립으로 이렇게 생성한 클래스 족 들을 자유롭게 바꿀 수 있다. 게다가, 구체적인 클래스 중의 하나를 생성하였기 때문에 이 시스템은 다른 종류의 클래스 족들로부터 우연한 사용을 유지하게 한다. 그러나 그것은 몇몇의 새로운 클래스 족들을 추가해야 하는 수고를 하여야 한다. 왜냐하면, 그러한 새로운 클래스 족들이 반환될 수 있는 상태를 새롭고 모호하지 않게 정의해야 하기 때문이다.

    반면에 생성된 추상화 팩토리의 모든 클래스들은 같은 상위 클래스를 가지고 있고, 다른 클래스들이 가지고 있는 메소드와는 다른 메소드를 추가하는 것을 방해하지 않는다.

'Development > 패턴자료' 카테고리의 다른 글

[펌] The Bridge Pattern  (0) 2011.08.13
[펌] The Adapter Pattern  (0) 2011.08.13
[펌] Summary of Structural Patterns  (0) 2011.08.13
[펌] Structural Patterns  (0) 2011.08.13
[펌] Some Background on Design Patterns  (0) 2011.08.13
안정적인 DNS서비스 DNSEver DNS server, DNS service
Posted by 키르히아이스
,