개요

프로그램이 커지면서 많은 클래스가 작성되면 그 관계도 서로 복잡하게 된다. 때문에 어떤 클래스를 사용할 경우 클래스 간 관계를 정확히 이해하고 사용할 필요가 있는데, 그 처리를 위해 어떠한 창구(=Facede)를 두는 것이 Facade 패턴이다.

 창구를 통해 시스템 내부의 복잡한 관계를 정리해서 외부에서는 단순한 인터페이스로 이용이 가능하도록 해준다.

 

 예제에서 Facede 역할을 하는 PageMaker 클래스는 외부에서는 단순히 makeWelcomePage() 메서드만을 인터페이스로 제공한다. 실제로 내부에서 시스템을 구성하는 요소들(Database클래스, HtmlWriter클래스)을 어떤 관계와 순서로 호출하는지는 외부에서 알 수가 없고, 알 필요도 없는 것이다.

역할

Facade 역할

 시스템이 제공하는 많은 기능(역할)들에 대해 단순한 인터페이스를 제공하는 창구 역할을 한다. 예제에서는 PageMaker 클래스.

 

시스템을 구성하는 역할들

  시스템을 구성하는 역할들은 각기 다른 기능이나 작업을 하며 Facade 역할에게 호출된다. 각각의 역할들은 Facade 역할을 특별히 고려하진 않는다. 예제에서는 Database클래스, HtmlWriter 클래스.

 

Client 역할

  Facade 역할을 이용하는 역할로 단순한 인터페이스로 기능을 사용할 수 있다. 예제에서는 Main 클래스.

 

이득 및 주의사항

 Facade의 핵심은 복잡한 구조를 단순하게 보여주는 것이다. 특히 외부에서 사용하는 인터페이스(API)를 단순하게 하는 것이다. 외부에서 단순한 API만으로 접근한다는 말은 약한 결합을 지향한다는 의미고 결과적으로 Facade로 구성된 시스템이나 모듈집합의 독립성이나 재사용성을 높여준다.

 

 Facade로 하위 패키지들을 묶고, 다시 그 Facade들을 묶는 상위 Facade 패턴을 적용하는 재귀적 구조를 사용하면 큰 시스템에서 다수의 모듈들을 보다 편리하게 관리할 수 있다.

 

 클래스들을 설계할 때 필드나 메소드의 접근지정자를 주의한다. 필요최소로 public을 지정해야 클래스의 수정이 쉬워진다.

 

예제 코드

//Facade 역할
package pagemaker;

import java.io.FileWriter;
import java.io.IOException;
import java.util.Properties;

public class PageMaker {
	private PageMaker() {
		
	}
	
	public static void makeWelcomePage(String mailaddr, String filename) {
		try {
			Properties mailprop = Database.getProperties("maildata");
			String username = mailprop.getProperty(mailaddr);
			HtmlWriter writer = new HtmlWriter(new FileWriter(filename));
			writer.title("Welcome to " + username + "'s page!");
			writer.paragraph(username + "의 페이지에 오신 걸 환영합니다.");
			writer.paragraph("메일을 기다리고 있습니다.");
			writer.mailto(mailaddr, username);
			writer.close();
			
			System.out.println(filename + " is created for " + mailaddr + " (" + username + ")");
		} catch(IOException e) {
			e.printStackTrace();
		}
	}
}


//시스템을 구성하는 모듈 역할1
package pagemaker;

import java.io.FileInputStream;
import java.io.IOException;
import java.util.Properties;

public class Database {
	private Database() {
		
	}
	public static Properties getProperties(String dbname) {
		
		String filename = dbname+".txt";
		Properties prop = new Properties();
		try {
			prop.load(new FileInputStream(filename));
		} catch(IOException e) {
			System.out.println("Warning : " + filename + " is not found.");
		}
		
		return prop;
	}
}


//시스템을 구성하는 모듈 역할2
package pagemaker;

import java.io.IOException;
import java.io.Writer;

public class HtmlWriter {
	private Writer writer;
	public HtmlWriter(Writer writer) {
		this.writer = writer;
	}
	
	public void title(String title) throws IOException{
		writer.write("<html>");
		writer.write("<head>");
		writer.write("<title>"+title+"</title>");
		writer.write("</head>");
		writer.write("<body>\n");
		writer.write("<h1>"+title+"</h1>\n");
	}
	
	public void paragraph(String msg) throws IOException {
		writer.write("<p>"+msg+"</p>");
	}
	
	public void link(String href, String caption) throws IOException{
		writer.write("<a href=\"" + href + "\">" + caption + "</a>");
	}
	
	public void mailto(String mailaddr, String username) throws IOException{
		link("mailto : " + mailaddr, username);
	}
	
	public void close() throws IOException{
		writer.write("</body>");
		writer.write("</html>\n");
		writer.close();
	}
}


//Client 역할
import pagemaker.PageMaker;

public class Main {
	public static void main(String[] args) {
		PageMaker.makeWelcomePage("programo@programo.com", "welcome.html");
	}
}


'디자인 패턴' 카테고리의 다른 글

17. Observer 패턴  (0) 2020.12.29
16. Mediator 패턴  (0) 2020.12.28
14. Chain of Responsibility 패턴  (0) 2020.12.22
13. Visitor 패턴  (0) 2020.12.17
12. Decorator 패턴  (0) 2020.12.16

+ Recent posts