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

  1. 7. 어댑터 패턴과 퍼사드 패턴
    1. 1. 어댑터 패턴
      1. 1-1. 정의
      2. 1-2. 클래스 어댑터 패턴
      3. 1-3. 객체 어댑터 패턴
      4. 1-4. 예제
      5. 1-5. 결론
    2. 2. 퍼사드 패턴
      1. 2-1. 정의
      2. 2-2. 디자인 원칙
      3. 3-3. 예제: XML트리
    3. 문서에 대하여

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);
	}
}

"정말 쉽죠?"

문서에 대하여