본문 바로가기
디자인 패턴

[디자인패턴]컴포지트(Composite)패턴

by violetoz 2013. 5. 27.

디자인패턴의 단골 패턴 중 하나인 컴포지트(Composite) 패턴입니다.

컴포지트 패턴은 간단히 말해서 


추상적인 상위 클래스 하나를 만들고,
그 클래스를 상속받는 다양한 자식 클래스들을 만들어
결국, 다양한 자식 클래스들을 마치 같은 종류의 클래스 다루듯이 동일시해서 사용하겠다는 패턴입니다.

 
이 컴포지트 패턴은 나중에 커맨드(Command) 패턴이나 방문자(Visitor) 패턴, 데코레이터(Decorator) 패턴 등에 
응용되서 사용되어질 수 있습니다. 상당히 유용한 패턴인거죠 !!

그리고 여기서 더 나아가 트리 구조와 같은 재귀적인(Recursive) 구조를 만들기 위해서도 유용하게 쓰입니다.

트리 구조의 가장 모범적인 예제로는 '파일 구조'가 있습니다.
각종 폴더와 파일들이 있으며, 특정 폴더 아래에는 또 다른 폴더들과 파일들이 존재하죠.


이를 컴포지트 패턴을 이용해서 표현해보도록 하겠습니다.

컴포지트 패턴은 다음과 같이 Component, Leaf, Composite 로 구성되어집니다.












public abstract class Component
{

public abstract Component add(Component cp);
public abstract void remove(Component cp);
... 



public class Leaf extends Component 
{

...



public class Composite extends Component 
{

private ArrayList arrChildren = new ArrayList();
public Component add(Component cp);
public abstract void remove(Component cp); 
...

}  

여기서 Leaf 역할은 File 클래스가, Composite 역할은 Folder 클래스가 맡게 됩니다.



대략적인 소스는 다음과 같습니다.
Component.java





01.package snowdeer.pattern.composite;
02. 
03.import java.io.IOException;
04. 
05.public abstract class Component
06.{
07.public abstract String getName();
08.public abstract int getSize();
09. 
10.public Component add(Component component) throws Exception
11.{
12.throw new IOException();
13.}
14. 
15.public void printList()
16.{
17.printList("");
18.}
19. 
20.protected abstract void printList(String strPrefix);
21. 
22.public String toString()
23.{
24.return getName() + "(" + getSize() + ")";
25.}
26.}




File.java



01.package snowdeer.pattern.composite;
02. 
03.import android.util.Log;
04. 
05.public class File extends Component
06.{
07.private String m_strName;
08.private int m_nSize;
09. 
10.public File(String strName, int nSize)
11.{
12.m_strName = strName;
13.m_nSize = nSize;
14.}
15. 
16.@Override
17.public String getName()
18.{
19.return m_strName;
20.}
21. 
22.@Override
23.public int getSize()
24.{
25.return m_nSize;
26.}
27. 
28.@Override
29.protected void printList(String strPrefix)
30.{
31.Log.i("Composite Pattern", strPrefix + "/" this);
32.}
33.}




Folder.java



01.package snowdeer.pattern.composite;
02. 
03.import java.util.ArrayList;
04.import java.util.Iterator;
05. 
06.import android.util.Log;
07. 
08.public class Folder<e> extends Component
09.{
10.private String m_strName;
11.private ArrayList arrFolders = new ArrayList();
12. 
13.public Folder(String strName)
14.{
15.m_strName = strName;
16.}
17. 
18.@Override
19.public String getName()
20.{
21.return m_strName;
22.}
23. 
24.@Override
25.public int getSize()
26.{
27.int _size = 0;
28.Iterator<folder> it = arrFolders.iterator();
29.while(it.hasNext() == true)
30.{
31.Component cp = (Component)it.next();
32._size = _size + cp.getSize();
33.}
34. 
35.return _size;
36.}
37. 
38.@Override
39.public Component add(Component component)
40.{
41.arrFolders.add(component);
42. 
43.return this;
44.}
45. 
46.@Override
47.protected void printList(String strPrefix)
48.{
49.Log.i("Composite Pattern", strPrefix + "/" this);
50. 
51.Iterator<folder> it = arrFolders.iterator();
52.while(it.hasNext() == true)
53.{
54.Component cp = (Component)it.next();
55.cp.printList(strPrefix + "/" + m_strName);
56.}
57.}
58.}
59.</folder></folder></e>




그리고 이렇게 만든 클래스를 활용해보는 테스트 예제 코드는 다음과 같습니다.


01.package snowdeer.pattern.activity;
02. 
03.import snowdeer.pattern.composite.File;
04.import snowdeer.pattern.composite.Folder;
05.import android.app.Activity;
06.import android.os.Bundle;
07.import android.util.Log;
08. 
09.public class ActMain extends Activity
10.{
11./** Called when the activity is first created. */
12.@Override
13.public void onCreate(Bundle savedInstanceState)
14.{
15.super.onCreate(savedInstanceState);
16.setContentView(R.layout.main);
17. 
18.try
19.{
20.Log.i("Composite Pattern""Creating folders and files....");
21. 
22.Folder rootFolder = new Folder("root");
23.Folder folder_1 = new Folder("folder_1");
24.Folder folder_2 = new Folder("folder_2");
25.Folder folder_3 = new Folder("folder_3");
26. 
27.rootFolder.add(folder_1);
28.rootFolder.add(folder_2);
29.rootFolder.add(folder_3);
30. 
31.folder_1.add(new File("file_1", 100));
32.folder_2.add(new File("file_2", 100));
33.folder_2.add(new File("file_3", 200));
34. 
35.Folder subFolder_1 = new Folder("subFolder_1");
36.Folder subFolder_2 = new Folder("subFolder_2");
37. 
38.folder_1.add(subFolder_1);
39.folder_1.add(subFolder_2);
40. 
41.subFolder_1.add(new File("sub_File_1", 100));
42.subFolder_1.add(new File("sub_File_2", 100));
43.subFolder_1.add(new File("sub_File_3", 100));
44. 
45.rootFolder.printList();
46.}
47.catch(Exception e)
48.{
49.e.printStackTrace();
50.}
51.}
52.}


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

패턴의 종류  (0) 2014.09.11
디자인패턴  (0) 2014.09.11
[디자인패턴]싱글톤(Singleton)패턴  (0) 2013.05.27