by-nc-sa     개발자, DBA가 함께 만들어가는 구루비 지식창고!

7. 어댑터 패턴과 퍼사드 패턴




7. 어댑터 패턴과 퍼사드 패턴

1. 어댑터 패턴

1-1. 정의

  • 한 클래스의 인터페이스를 클라이언트에서 사용하고자 하는 다른 인터페이스로 변환합니다.
    어댑터를 이용하면 인터페이스 호환성 문제 ?문에 같이 쓸 수 없는 클래스들을 연결해서 쓸 수 있습니다.

1-2. 클래스 어댑터 패턴

  • 단점: 상속(Generalzation)을 활용하기때문에 유연하지 못하다.
  • 장점: 어댑터(Adapter)를 전체를 다시 구현할 필요가 없다.(빠르다)
  • 주의: 클래스 어댑터에서는 다중상속을 이용하기 때문에 자바에서는 쓸 수 없습니다.
    • 쓸수있습니다.(간접적 다중상속 지원)
  • 코드
    public class Adaptee {
    	public void specificRequest() {
    		System.out.println("Adaptee.speificRequest()");
    	}
    }
    
    public interface Target {
    	public void request();
    }
    
    public class Adapter extends Adaptee implements Target {	
    	public void request() {
    		this.specificRequest(); // 다중상속
    	}
    }
    
    public class Client {
    	public static void main(String[] args) {
    		Target target = new Adapter();
    		
    		target.request();		
    	}
    }
    
  • 결과 : "Adaptee.speificRequest()" 출력

1-3. 객체 어댑터 패턴

  • 단점: 어댑터(Adapter)클래스의 대부분의 코드를 구현해야하기때문에 효율적이지 못하다
  • 장점: 구성(Composition)을 사용하기 때문에 더 뛰어나다.(유연하다)
  • 코드
    public class Adaptee {
    	public void specificRequest() {
    		System.out.println("Adaptee.speificRequest()");
    	}
    }
    
    public interface Target {
    	public void request();
    }
    
    public class Adapter implements Target {
    	Adaptee adaptee = new Adaptee(); // 객체를 만들고
    	
    	public void request() {
    		adaptee.specificRequest();	// 객체를 연결한다.
    	}
    }
    
    public class Client {
    	public static void main(String[] args) {
    		Target target = new Adapter();
    		
    		target.request();		
    	}
    }
    
  • 결과 : "Adaptee.speificRequest()" 출력

1-4. 예제

  • 책: Emumeration -> Adapter -> Interator

1-5. 결론

  • 구식의 110V코드(옛코드1)에 220V아답터(신규작성코드)를 꼽으면, 최신의 220V(새코드2)를 사용할수 있는 것 처럼
    옛코드를 새코드처럼 사용할 수 있다.

2. 퍼사드 패턴

2-1. 정의

  • 어떤 서브시스템의 일련의 인터페이스에 대한 통합된 인터페이스를 제공합니다.
    퍼사드에서 고수준 인터페이스를 정의하기 때문에 서브시스템을 더 쉽게 사용할 수 있습니다.

2-2. 디자인 원칙

  • 최소 지식 원칙 - 정말 친한 친구하고만 얘기하라.
  • -> Facade패턴을 사용하여 정말 친한 친구를 만들어라.
  • -> Facade패턴: 일련의 행동을 그룹화 시켜라.
  • 시스템을 디자인할 때, 어떤 객체든 그 객체와 상호작용하는 것들에 주의하라.
  • 의존도를 복잡하게 만들면, 코드 변경시 낭패.

3-3. 예제: XML트리

  • 코드: Node
    import java.util.ArrayList;
    import java.util.Collection;
    
    /**
     * 
     * Node
     * 
     * Tree 사용 노드
     * 
     * @author 장선웅
     *
     */
    public class Node {	
    	String name = null; // 이름
    	String value = null; // 값
    	
    	Node parent = null; // 부모노드
    	
    	// 이펙티브 자바 항목 34(p205) : 인터페이스 타입으로 객체를 참조하라.
    	// 자식노드들.
    	Collection<Node> childs = new ArrayList<Node>(); 
    	
    	Node(Node parent, String attributeName, String attributeValue) {
    		this.parent = parent;
    		if(parent != null)
    			parent.addChilde(this);
    		
    		name = attributeName;
    		value = attributeValue;
    	}
    	
    	void addChilde(Node child) {
    		childs.add(child);
    	}
    }
    
  • 코드: Tree
    import java.util.Collection;
    import java.util.HashSet;
    
    /**
     * SimpleTree 
     * 
     * 간단한 트리
     * 
     * @author 장선웅
     *
     */
    
    public class Tree {
    	Node root = null;
    	
    	Tree(String rootName, String rootValue) {
    		createRootNode(rootName, rootValue);
    	}
    		
    	/**
    	 * 노드의 앞부분을 출력한다
    	 * 
    	 * ex) <NAME>TEXT
    	 * 
    	 * @param node 부모노드
    	 * @param depth 트리깊이
    	 * @return 자식노드
    	 */
    	static Collection<Node> print(Node node, int depth) {
    		for(int i=0; i<depth; i++) {
    			System.out.print("\t");
    		}
    		System.out.println("<" + node.name + ">");
    		
    		if (!(node.value instanceof String) || !(node.value.equals(""))) { 
    			for(int i=0; i<=depth; i++) {
    				System.out.print("\t");
    			}
    			System.out.println(node.value);
    		}
    		
    		return node.childs;
    	}
    	
    	/**
    	 * 노드의 뒷부분을 출력한다.
    	 * 
    	 * ex) </NAME>
    	 * 
    	 * @param node 부모노드
    	 * @param depth 트리깊이
    	 * @return 자식노드
    	 */
    	static Collection<Node> printEnd(Node node, int depth) {
    		for(int i=0; i<depth; i++) {
    			System.out.print("\t");
    		}
    		System.out.println("</" + node.name + ">");
    		
    		return node.childs;
    	}
    	
    	/**
    	 * 트리를 출력한다.
    	 * @param root root노드
    	 * @param depth root의 깊이
    	 */
    	static void printAll(Node root, int depth) {
    		Collection<Node> childnodes = null;		
    				
    		childnodes = print(root, depth);
    		
    		if(childnodes.size() > 0)
    			++depth;
    		
    		for(Node child: childnodes) {
    			printAll(child, depth);
    		}		
    		
    		if(childnodes.size() > 0)
    			--depth;
    		printEnd(root, depth);
    	}
    	
    	/**
    	 * root노드를 생성한다.
    	 * 
    	 * @param attributeName root노드 이름
    	 * @param attributeValue root노드 값
    	 */
    	void createRootNode(String attributeName, String attributeValue) {
    			root = new Node(null, attributeName, attributeValue);
    	}
    	
    	/**
    	 * 자식노드를 생성한다.
    	 * 
    	 * @param parent 자식노드의 부모
    	 * @param attributeName 자식노드의 이름
    	 * @param attributeValue 자식노드의 값
    	 * @return 생성된 자식노드
    	 */
    	static Node createChildNode(Node parent, String attributeName, String attributeValue) {		
    		
    		return new Node(parent, attributeName, attributeValue);
    	}
    	 
    	Node getRoot() {
    		return root;
    	}
    	
    	/**
    	 * 스터디 회원목록을 출력한다.
    	 * 
    	 * @param args
    	 */
    	public static void main(String[] args) {	
    		Tree tree = new Tree("스터디", "");
    		
    		Node root = tree.getRoot();
    		
    			Node oracle = tree.createChildNode(root, "그룹", "대용량데이터베이스");		
    				Node ora1 = tree.createChildNode(oracle, "멤버", "많음..;");
    				
    			Node java = tree.createChildNode(root, "그룹", "자바웹개발");
    				
    				Node member1 = tree.createChildNode(java, "멤버", "유진우");				
    					Node member1a = tree.createChildNode(member1, "디자인패턴", "템플릿 메소드");
    					
    				Node member2 = tree.createChildNode(java, "멤버", "장선웅");
    					Node member2a = tree.createChildNode(member2, "디자인패턴", "어뎁터 & 퍼사드");
    					Node member2b = tree.createChildNode(member2, "이펙티브자바", "C구분 바꾸기");
    				
    				Node member3 = tree.createChildNode(java, "멤버", "장선웅");
    					Node member3a = tree.createChildNode(member3, "디자인패턴", "어뎁터 & 퍼사드");
    					Node member3b = tree.createChildNode(member3, "이펙티브자바", "C구분 바꾸기");
    		
    		tree.printAll(tree.root, 0);
    	}
    }
     
    
  • 결과
    <스터디>
    	<그룹>
    		대용량데이터베이스
    		<멤버>
    			많음..;
    		</멤버>
    	</그룹>
    	<그룹>
    		자바웹개발
    		<멤버>
    			유진우
    			<디자인패턴>
    				템플릿 메소드
    			</디자인패턴>
    		</멤버>
    		<멤버>
    			장선웅
    			<디자인패턴>
    				어뎁터 & 퍼사드
    			</디자인패턴>
    			<이펙티브자바>
    				C구분 바꾸기
    			</이펙티브자바>
    		</멤버>
    		<멤버>
    			장선웅
    			<디자인패턴>
    				어뎁터 & 퍼사드
    			</디자인패턴>
    			<이펙티브자바>
    				C구분 바꾸기
    			</이펙티브자바>
    		</멤버>
    	</그룹>
    </스터디>
    
  • 퍼사드 적용
    import java.util.Collection;
    import java.util.HashSet;
    
    /**
     * SimpleTree 
     * 
     * 간단한 트리
     * 
     * @author 장선웅
     *
     */
    
    public class Tree {
    	Node root = null;
    	
    	Tree(String rootName, String rootValue) {
    		createRootNode(rootName, rootValue);
    	}
    		
    	/**
    	 * 노드의 앞부분을 출력한다
    	 * 
    	 * ex) <NAME>TEXT
    	 * 
    	 * @param node 부모노드
    	 * @param depth 트리깊이
    	 * @return 자식노드
    	 */
    	static Collection<Node> print(Node node, int depth) {
    		for(int i=0; i<depth; i++) {
    			System.out.print("\t");
    		}
    		System.out.println("<" + node.name + ">");
    		
    		if (!(node.value instanceof String) || !(node.value.equals(""))) { 
    			for(int i=0; i<=depth; i++) {
    				System.out.print("\t");
    			}
    			System.out.println(node.value);
    		}
    		
    		return node.childs;
    	}
    	
    	/**
    	 * 노드의 뒷부분을 출력한다.
    	 * 
    	 * ex) </NAME>
    	 * 
    	 * @param node 부모노드
    	 * @param depth 트리깊이
    	 * @return 자식노드
    	 */
    	static Collection<Node> printEnd(Node node, int depth) {
    		for(int i=0; i<depth; i++) {
    			System.out.print("\t");
    		}
    		System.out.println("</" + node.name + ">");
    		
    		return node.childs;
    	}
    	
    	/**
    	 * 트리를 출력한다.
    	 * @param root root노드
    	 * @param depth root의 깊이
    	 */
    	static void printAll(Node root, int depth) {
    		Collection<Node> childnodes = null;		
    				
    		childnodes = print(root, depth);
    		
    		if(childnodes.size() > 0)
    			++depth;
    		
    		for(Node child: childnodes) {
    			printAll(child, depth);
    		}		
    		
    		if(childnodes.size() > 0)
    			--depth;
    		printEnd(root, depth);
    	}
    	
    	/**
    	 * root노드를 생성한다.
    	 * 
    	 * @param attributeName root노드 이름
    	 * @param attributeValue root노드 값
    	 */
    	void createRootNode(String attributeName, String attributeValue) {
    			root = new Node(null, attributeName, attributeValue);
    	}
    	
    	/**
    	 * 자식노드를 생성한다.
    	 * 
    	 * @param parent 자식노드의 부모
    	 * @param attributeName 자식노드의 이름
    	 * @param attributeValue 자식노드의 값
    	 * @return 생성된 자식노드
    	 */
    	static Node createChildNode(Node parent, String attributeName, String attributeValue) {		
    		
    		return new Node(parent, attributeName, attributeValue);
    	}
    	 
    	Node getRoot() {
    		return root;
    	}
    	
    	// 간단한 퍼사드 패턴을 이용해서 복잡한 행동을 일련의 메소드/클래스로 변환시킨다.
    	public void addDatas() {
    	
    		Node root = getRoot();
    		
    		Node oracle = createChildNode(root, "그룹", "대용량데이터베이스");		
    			Node ora1 = createChildNode(oracle, "멤버", "많음..;");
    			
    		Node java = createChildNode(root, "그룹", "자바웹개발");
    			
    			Node member1 = createChildNode(java, "멤버", "유진우");				
    				Node member1a = createChildNode(member1, "디자인패턴", "템플릿 메소드");
    				
    			Node member2 = createChildNode(java, "멤버", "장선웅");
    				Node member2a = createChildNode(member2, "디자인패턴", "어뎁터 & 퍼사드");
    				Node member2b = createChildNode(member2, "이펙티브자바", "C구분 바꾸기");
    			
    			Node member3 = createChildNode(java, "멤버", "장선웅");
    				Node member3a = createChildNode(member3, "디자인패턴", "어뎁터 & 퍼사드");
    				Node member3b = createChildNode(member3, "이펙티브자바", "C구분 바꾸기");
    	}
    	/**
    	 * 스터디 회원목록을 출력한다.
    	 * 
    	 * @param args
    	 */
    	public static void main(String[] args) {		
    		Tree tree = new Tree("스터디", "");
    		
    		tree.addDatas(); // 정의한 메소드 호출
    		
    		printAll(tree.getRoot(), 0);
    	}
    }
    

"정말 쉽죠?"

문서에 대하여

  • 최초작성자 : 장선웅
  • 최초작성일 : 2008년 03월 25일
  • 이 문서는 HeadFirst Design Patterns을 정리한 내용 입니다.
  • 이 문서는 오라클클럽 [자바 웹개발자 스터디] 모임에서 작성하였습니다.
  • 이 문서를 다른 블로그나 홈페이지에 퍼가실 경우에는 출처를 꼭 밝혀 주시면 고맙겠습니다.~^^

문서정보

Enter labels to add to this page:
Please wait 
Looking for a label? Just start typing.