Pattern - Pacade
혁신을 할 때는 모든 사람들이 당신을 미쳤다고 할 테니, 그들 말에 준비가 되어 있어야 한다. - 래리 앨리슨 ( 오라클 CEO )
의도
한 서브 시스템 내의 인터페이스 집합에 대한 획일화된 하나의 인터페이스를 제공하는 패턴으로, 서브 시스템을 사용하기 쉽도록 상위 수준의 인터페이스를 제공합니다.
동기
- 시스템을 서브시스템으로 구조화 하면 복잡성을 줄이는 데에 큰 도움이 됩니다. 공통적인 설계 목표는 서브시스템들 사이의 의사소통 및 종속성을 최소화하려는 것입니다.
한 예로, 응용 프로그램이 컴파일러 시스템에 접근할 수 있는 어떤 프로그래밍 환경을 가정했을 때, 해당 컴파일러의 서브시스템에는 Scanner, Parser, BytecodStream 등의 클래스를 포함합니다. 이때 응용프로그램의 어느 특정 부분은 컴파일러에 정의된 이 클래스를 직접사용해야할 수 있지만, 대부분의 응용 프로그램들은 이런 구체적인 내용에 상관없이 파싱이나 코드 생성 단계를 이용하기만 합니다.
활용성
- 복잡한 서브 시스템에 대한 단순한 인터페이스 제공이 필요할 때, 시스템 범위가 확장되면, 또한 구체적으로 설계되면 서브 시스템은 계속 복잡해집니다. 또한 패턴을 적용하면 확장성을 고려하여 설계되기 때문에, 작은 클래스가 만들어지게 됩니다. 이런 과정은 서브 시스템을 재사용 가능한 것으로 만들어 주고, 재정의 할 수 있는 단위가 되도록 해 주기도 하지만, 실제 이런 상세한 재설계나 정제의 내용까지 파악할 필요가 없는 개발자들에게 복잡해진 각각의 클래스들을 다 이해하면서 서브시스템을 다 사용하기란 어려운 일입니다. 이럴 때 퍼사드 패턴은 서브시스템에 대한 단순하면서도 기본적인 인터페이스를 제공함으로써 대부분의 개발자들에게 적합한 클래스 형태를 제공합니다.
- 추상 개념에 대한 구현 클래스와 사용자 사이에 너무 많은 종속성이 존재할 때,
- 서브 시스템을 계층화 시킬 때, 퍼사드 패턴을 사용하여 각 서브 시스템의 계층에 대한 접근점을 제공합니다.
- 서브 시스템의 구성 요소를 보호할 수 있으며, 서브 시스템과 사용자 코드 간의 결합도를 약하게 만들 수 있다.
항목에 대한 설명
-
퍼사드 Compiler 단순하고 일관된 통합 인터페이스를 제공하며, 서브시스템을 구성하는 어떤 클래스가 어떤 요청을 처리해야 하는지 알고 있으며, 사용자의 요청을 해당 서브 시스템 객체에 전달합니다.
-
서브시스템 클래스들 Scanner, Parser, Program Node 서브 시스템의 기능을 구현하고, Facade 객체로 할당된 작업을 실제로 처리하지만 Facade 에 대한 아무런 정보가 없습니다. 즉, 이들에 대한 어떤 참조자도 가지고 있지 않습니다
코드 예제 - 기본
package DesignPattern.gof_pacade.sample01.JVMComponent;
import DesignPattern.gof_pacade.sample01.ClassLoadSubSystem;
import DesignPattern.gof_pacade.sample01.JVMComponent.builder.JVMComponent;
public class JavacLoader {
public static void main(String[] args) {
JVMComponent.Builder builder = new JVMComponent.Builder();
builder.Heap(new Heap());
builder.JavaThreads(new JavaThreads());
builder.MethodArea(new MethodArea());
builder.ProgramCounterRegisters(new ProgramCounterRegisters());
builder.NativeInternalThreads(new NativeInternalThreads());
ClassLoadSubSystem classLoadSubSystem = new ClassLoadSubSystem(builder.build());
classLoadSubSystem.ControlVariables();
}
}
package DesignPattern.gof_pacade.sample01;
import DesignPattern.gof_pacade.sample01.JVMComponent.Element.JVMElement;
import DesignPattern.gof_pacade.sample01.JVMComponent.builder.JVMComponent;
public class ClassLoadSubSystem {
public JVMComponent jvmComponent;
public ClassLoadSubSystem(JVMComponent jvmComponent){
this.jvmComponent = jvmComponent;
}
public void ControlVariables(){
JVMElement methodArea = jvmComponent.getJVMCompoentOrNull("MethodArea");
methodArea.doProcess();
}
}
package DesignPattern.gof_pacade.sample01.JVMComponent.Element;
public abstract class JVMElement {
public abstract void doProcess();
}
package DesignPattern.gof_pacade.sample01.JVMComponent;
import DesignPattern.gof_pacade.sample01.JVMComponent.Element.JVMElement;
public class Heap extends JVMElement {
public void doProcess() {
forHeapSetting();
}
private void forHeapSetting(){
}
}
package DesignPattern.gof_pacade.sample01.JVMComponent;
import DesignPattern.gof_pacade.sample01.JVMComponent.Element.JVMElement;
public class JavaThreads extends JVMElement {
@Override
public void doProcess() {
forJavaThreadSetting();
}
private void forJavaThreadSetting(){
}
}
package DesignPattern.gof_pacade.sample01.JVMComponent;
import DesignPattern.gof_pacade.sample01.JVMComponent.Element.JVMElement;
public class MethodArea extends JVMElement {
public void doProcess() {
forMethodAreaSetting();
}
private void forMethodAreaSetting(){
}
}
package DesignPattern.gof_pacade.sample01.JVMComponent;
import DesignPattern.gof_pacade.sample01.JVMComponent.Element.JVMElement;
public class NativeInternalThreads extends JVMElement {
public void doProcess() {
forNativeInternalThreadSetting();
}
private void forNativeInternalThreadSetting(){
}
}
package DesignPattern.gof_pacade.sample01.JVMComponent;
import DesignPattern.gof_pacade.sample01.JVMComponent.Element.JVMElement;
public class ProgramCounterRegisters extends JVMElement {
public void doProcess() {
forProgramCounterRegisters();
}
private void forProgramCounterRegisters(){
}
}
코드 예제 - Builder 패턴을 이용한 JVM Component 호출
package DesignPattern.gof_pacade.sample01.JVMComponent.builder;
import DesignPattern.gof_pacade.sample01.JVMComponent.*;
import DesignPattern.gof_pacade.sample01.JVMComponent.Element.JVMElement;
public class JVMComponent {
private final Heap heap;
private final JavaThreads javaThreads;
private final MethodArea methodArea;
private final NativeInternalThreads nativeInternalThreads;
private final ProgramCounterRegisters programCounterRegisters;
static class Builder{
private Heap heap;
private JavaThreads javaThreads;
private MethodArea methodArea;
private NativeInternalThreads nativeInternalThreads;
private ProgramCounterRegisters programCounterRegisters;
public Builder Heap(Heap heap){
this.heap = heap;
return this;
}
public Builder JavaThreads(JavaThreads javaThreads){
this.javaThreads = javaThreads;
return this;
}
public Builder MethodArea(MethodArea methodArea){
this.methodArea = methodArea;
return this;
}
public Builder NativeInternalThreads(NativeInternalThreads nativeInternalThreads){
this.nativeInternalThreads = nativeInternalThreads;
return this;
}
public Builder ProgramCounterRegisters(ProgramCounterRegisters programCounterRegisters){
this.programCounterRegisters = programCounterRegisters;
return this;
}
public JVMComponent build(){
return new JVMComponent(this);
}
}
private JVMComponent(Builder build){
this.heap = build.heap;
this.javaThreads = build.javaThreads;
this.methodArea = build.methodArea;
this.nativeInternalThreads = build.nativeInternalThreads;
this.programCounterRegisters = build.programCounterRegisters;
}
public JVMElement getJVMCompoentOrNull(String type){
switch (type){
case "Heap" :
return heap;
case "JavaThreads" :
return javaThreads;
case "MethodArea" :
return methodArea;
case "NativeInternalThreads" :
return nativeInternalThreads;
case "ProgramCounterRegisters" :
return programCounterRegisters;
}
return null;
}
}