문서 보기역링크PDF로 내보내기맨 위로 이 문서는 읽기 전용입니다. 원본을 볼 수는 있지만 바꿀 수는 없습니다. 문제가 있다고 생각하면 관리자에게 문의하세요. # Composite Pattern 여배우인 벨라 호크(Bella Hock)가 소셜 네트워크에서 사용자 아바타를 보지 못하고 있다. "모든 것이 검은 색이예요. 이거 블랙홀인가요?" 페드로: 이거 검정 사각형이네요. 이브: 흠, 이쪽도 같은 문제가 있어요. 페드로: 마지막에 추가된 기능이 사용자 아바타에 버그를 만든 것 같네요. 이브: 이상하네요, 아바타는 다른 요소들과 같은 방식으로 랜더링해요. 하지만 아바타는 눈에 보이는 거죠. 페드로: 같은 방식으로 랜더링하는 거 확실해요? 이브: 글쎄요… 아니요. 코드를 파 본다. 페드로: 도대체 이 코드들이 뭘 하는 거죠? 이브: 누군가 복사해서 붙여넣기를 했네요. 하지만 아바타에 변경 사항을 반영하는 것을 잊었어요. 페드로: 이 코드를 누가 작성했는지 확인해 보죠, [[git-blame]] 이브: 확인하는 것도 좋긴 한데, 이 문제를 고칠 필요가 있어요. 페드로: 여기에 한 줄 추가하면 간단하죠. 이브: 제 말은, 진짜 문제를 풀자는 거에요. 같은 블럭들을 처리하는데, 비슷한 코드 2개가 왜 필요하죠? 페드로: 맞네요. 합성 패턴을 사용해서 전체 페이지 랜더링을 처리할 수 있을 것 같아요. 랜더링하는 가장 작은 요소는 블럭이구요. <code> public interface Block { void addBlock(Block b); List<Block> getChildren(); void render(); } </code> 페드로: 당연히 블럭은 다른 블럭을 포함할 수 있어요. 그게 바로 합성 패턴이죠. 구체적인 블럭 몇 개를 만들어 보죠. <code> public class Page implements Block { } public class Header implements Block { } public class Body implements Block { } public class HeaderTitle implements Block { } public class UserAvatar implements Block { } </code> 페드로: 그리고 모든 구체적인 요소들을 Block인 것처럼 다룰 수 있죠. <code> Block page = new Page(); Block header = new Header(); Block body = new Body(); Block title = new HeaderTitle(); Block avatar = new UserAvatar(); page.addBlock(header); page.addBlock(body); header.addBlock(title); header.addBlock(avatar); page.render(); </code> 페드로: 이것은 구조 패턴이에요. 개체들을 합성하는 좋은 방법이죠. 그래서 합성이라고 불리는 거죠. 이브: 저기요. 합성은 단순한 트리 구조네요. 페드로: 그렇죠. 이브: 모든 자료구조를 위한 패턴이 있나요? 페드로: 아니요. 단지 리스트와 트리만을 위한 패턴이 있죠. 이브: 사실, 트리는 리스트로 표현할 수 있어요. 페드로: 어떻게요? 이브: 리스트의 첫 요소는 노드이고요. 그 다음 요소들은 자식들이., 그리고 그들 각각은… 페드로: 이해했어요. 이브: 좀 더 설명하자면, 다음과 같이 트리가 있어요. <code> A / | \ B C D | | / \ E H J K / \ /|\ F G L M N </code> 이브: 그리고 이 트리를 나타내는 리스트가 다음처럼 돼요. <code> (def tree '(A (B (E (F) (G))) (C (H)) (D (J) (K (L) (M) (N))))) </code> 페드로: 괄호가 많네요! 이브: 괄호는 구조를 만드는 거죠, 알다시피. 페드로: 하지만 파악하기 어려워요. 이브: 기계한테는 쉽죠. 트리를 처리하는 [[tree-seq]]라는 멋진 함수가 있어요 <code> (map first (tree-seq next rest tree)) => (A B E F G C H D J K L M N) </code> 이브: 더 복잡한 순회가 필요하다면, [[clojure.walk]]를 사용하면 돼요. 페드로: 모르겠네요, 모든 것이 좀 더 어려워 보이네요. 이브: 아니요, 모든 트리를 자료구조 하나로 정의하고, 그것에 대해 동작하는 하나의 함수만을 사용하는 것이예요. 페드로: 이 함수가 하는 일이 뭐죠? 이브: 트리를 순회하면서 모든 노드에 함수를 적용하는 거죠, 우리의 경우에는 각 컴포넌트들을 랜더링하는 거구요. 페드로: 모르겠네요, 전 트리를 다루기에는 경험이 부족한가 봐요. 다음으로 가죠. open/composite-pattern.txt 마지막으로 수정됨: 2021/11/22 11:18저자 127.0.0.1