Post

โ›“๏ธ Java Design-Pattern โ…ซ - Composite

โ›“๏ธ Java Design-Pattern โ…ซ - Composite

๐Ÿ“— ใ€ŽJAVA ์–ธ์–ด๋กœ ๋ฐฐ์šฐ๋Š” ๋””์ž์ธ ํŒจํ„ด : ์‰ฝ๊ฒŒ ๋ฐฐ์šฐ๋Š” GoF์˜ 23๊ฐ€์ง€ ๋””์ž์ธ ํŒจํ„ดใ€๋ฅผ ์ฝ๊ณ  ์ •๋ฆฌํ•œ ๊ธ€์ž…๋‹ˆ๋‹ค.

Composite ํŒจํ„ด์ด๋ž€?

  • Composite๋ž€ ํ˜ผํ•ฉ๋ฌผ, ๋ณตํ•ฉ๋ฌผ์ด๋ผ๋Š” ๋œป์œผ๋กœ, ๊ทธ๋ฆ‡๊ณผ ๋‚ด์šฉ๋ฌผ์„ ๋™์ผ์‹œํ•˜์—ฌ ์žฌ๊ท€์ ์ธ ๊ตฌ์กฐ๋ฅผ ๋งŒ๋“œ๋Š” ๋””์ž์ธ ํŒจํ„ด์ด๋‹ค.

์˜ˆ์ œ ํ”„๋กœ๊ทธ๋žจ

  • ๋‹ค์Œ์€ ํŒŒ์ผ๊ณผ ๋””๋ ‰ํ„ฐ๋ฆฌ๋ฅผ ๋„์‹์ ์œผ๋กœ ํ‘œํ˜„ํ•˜๋Š” ํ”„๋กœ๊ทธ๋žจ์ด๋‹ค.

  • Fileย ํด๋ž˜์Šค๋Š” ํŒŒ์ผ์„ ๋‚˜ํƒ€๋‚ด๋ฉฐ,ย Directoryย ํด๋ž˜์Šค๋Š” ๋””๋ ‰ํ„ฐ๋ฆฌ๋ฅผ ๋‚˜ํƒ€๋‚ธ๋‹ค.ย 
  • Entryย ํด๋ž˜์Šค๋Š” ๊ทธ ๋‘˜์„ ์ทจํ•ฉํ•˜๋Š” ํ˜•ํƒœ์ธ ๋””๋ ‰ํ„ฐ๋ฆฌ ์—”ํŠธ๋ฆฌ๋ฅผ ๋‚˜ํƒ€๋‚ธ๋‹ค.

Entryย ํด๋ž˜์Šค

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public abstract class Entry {
	public abstract String getName();
    
    public abstract int getSize();
    
    public void printList() {
    	printList("");
    }
    
    protected abstract void printList(String prefix);
    
    @Override
    public String toString() {
    	return getName() + "(" + getSize() + ")";
    }
}
  • ๋””๋ ‰ํ„ฐ๋ฆฌ ์—”ํŠธ๋ฆฌ๋ฅผ ํ‘œํ˜„ํ•˜๋Š” ์ถ”์ƒ ํด๋ž˜์Šค์ด๋‹ค.
  • ํ•˜์œ„ ํด๋ž˜์Šค๋กœย File,ย Directoryย ํด๋ž˜์Šค๊ฐ€ ๋งŒ๋“ค์–ด์ง„๋‹ค.
  • ๋””๋ ‰ํ„ฐ๋ฆฌ ์—”ํŠธ๋ฆฌ๋Š” ์ด๋ฆ„๊ณผ ์‚ฌ์ด์ฆˆ๋ฅผ ๊ฐ–๊ณ  ์žˆ์œผ๋ฉฐ, ๊ฐ๊ฐ์„ ์–ป๋Š”ย getterย ๋ฉ”์†Œ๋“œ๋Š” ํ•˜์œ„ ํด๋ž˜์Šค์— ๊ตฌํ˜„์„ ๋งก๊ธด๋‹ค.
  • printListย ๋ฉ”์†Œ๋“œ๋Š” ์ธ์ˆ˜ ์—ฌ๋ถ€์— ๋”ฐ๋ผ ์˜ค๋ฒ„๋กœ๋”ฉ ๋˜์–ด ์žˆ๋‹ค.

Fileย ํด๋ž˜์Šค

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
public class File extends Entry {
	private String name;
    private int size;
    
    public File(String name, int size) {
    	this.name = name;
        this.size = size;
    }
    
    @Override
    public String getName() {
    	return name;
    }
    
    @Override
    public int getSize() {
    	return size;
    }
    
    @Override
    protected void printList(String prefix) {
	    System.out.println(prefix + "/" + this);
    }
}
  • printListย ๋ฉ”์†Œ๋“œ์ฒ˜๋Ÿผ ๊ฐ์ฒด๋ฅผ ์ถœ๋ ฅํ•˜๋ฉด ์ž๋™์œผ๋กœ ํ•ด๋‹น ๊ฐ์ฒด์˜ย toString()์ด ํ˜ธ์ถœ๋œ๋‹ค.
  • Entryย ํด๋ž˜์Šค์—์„œ ์„ ์–ธ๋œ ์ถ”์ƒ ๋ฉ”์†Œ๋“œ๋ฅผ ๋ชจ๋‘ ๊ตฌํ˜„ํ–ˆ์œผ๋ฏ€๋กœย Fileย ํด๋ž˜์Šค๋Š” ์ถ”์ƒ ํด๋ž˜์Šค๊ฐ€ ์•„๋‹ˆ๋‹ค.

Directoryย ํด๋ž˜์Šค

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
import java.util.ArrayList;
import java.util.List;

public class Directory extends Entry {
	private String name;
    private List<Entry> directory = new ArrayList<>();
    
    public Directory(String name) {
    	this.name = name;
    }
    
    @Override
    public String getName() {
    	return name;
    }
    
    @Override
    public int getSize() {
    	int size = 0;
        for (Entry entry : directory) {
        	size += entry.getSize();
        }
        
        return size;
    }
    
    @Override
    protected void printList(String prefix) {
    	System.out.println(prefix + "/" + this);
        for (Entry entry : directory) {
        	entry.printList(prefix + "/" + name);
        }
    }
    
 	public Entry add(Entry entry) {
    	directory.add(entry);
        return this;
    }
}
  • Directoryย ํด๋ž˜์Šค๋Š” ์‚ฌ์ด์ฆˆ๋ฅผ ๋™์ ์œผ๋กœ ๊ณ„์‚ฐํ•ด์„œ ๊ตฌํ•˜๋ฏ€๋กœย sizeย ํ•„๋“œ๊ฐ€ ๋”ฐ๋กœ ์—†๋‹ค.
  • size += entry.getSize();๋ฅผ ํ†ตํ•ด ์‚ฌ์ด์ฆˆ๋ฅผ ๊ตฌํ•˜๋Š”๋ฐ,ย entry๊ฐ€ย Fileย ํด๋ž˜์Šค์˜ ์ธ์Šคํ„ด์Šค์ด๋“ ,ย Directoryย ํด๋ž˜์Šค์˜ ์ธ์Šคํ„ด์Šค์ด๋“ ย Entry์˜ ํ•˜์œ„ ํด๋ž˜์Šค์˜ ์ธ์Šคํ„ด์Šค์ด๋ฏ€๋กœ ์•ˆ์‹ฌํ•˜๊ณ ย getSizeย ๋ฉ”์†Œ๋“œ๋ฅผ ํ˜ธ์ถœํ•  ์ˆ˜ ์žˆ๋‹ค.
  • ์ด์™ธ์—๋„ย add,ย printListย ๋“ฑ์˜ ๋ฉ”์†Œ๋“œ๋„ย entry๊ฐ€ ํŒŒ์ผ์ธ์ง€ ๋””๋ ‰ํ† ๋ฆฌ์ธ์ง€ ์กฐ์‚ฌํ•˜์ง€ ์•Š๊ณ  ๊ทธ๋ฆ‡๊ณผ ๋‚ด์šฉ๋ฌผ์„ ๋™์ผ์‹œํ•˜์—ฌ ์ฒ˜๋ฆฌํ•œ๋‹ค.

Mainย ํด๋ž˜์Šค

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
public class Main {
	public static void main(String[] args) {
    	System.out.println("Making root entries...");
        Directory rootDir = new Directory("root");
        Directory binDir = new Directory("bin");
        Directory tmpDir = new Directory("tmp");
        Directory usrDir = new Directory("usr");
        
        rootDir.add(binDir);
        rootDir.add(tmpDir);
        rootDir.add(usrDir);
        
        binDir.add(new File("vi", 10000));
        binDir.add(new File("latex", 20000));
        
        rootDir.printList();
        System.out.println();
        
        System.out.println("Making user entries...");
        Directory youngjin = new Directory("youngjin");
        Directory gildong = new Directory("gildong");
        Directory dojun = new Directory("dojun");
        
        usrDir.add(youngjin);
        usrDir.add(gildong);
        usrDir.add(dojun);
        
        youngjin.add(new File("diary.html", 100));
        youngjin.add(new File("Composite.java", 200));
		gildong.add(new File("memo.txt", 300));
        dojun.add(new File("game.doc", 400));
        dojun.add(new File("junk.mail", 500));
        
        rootDir.printList();
    }
}
  • Mainย ํด๋ž˜์Šค์˜ ํŒŒ์ผ๊ณผ ๋””๋ ‰ํ„ฐ๋ฆฌ ๊ณ„์ธต์„ ๊ทธ๋ฆฌ๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
root
โ”œโ”€โ”€ bin
โ”‚   โ”œโ”€โ”€ vi
โ”‚   โ””โ”€โ”€ latex
โ”œโ”€โ”€ tmp
โ””โ”€โ”€ usr
    โ”œโ”€โ”€ yongjin
	โ”‚	โ”œโ”€โ”€ diary.html
	โ”‚   โ””โ”€โ”€ Composite.java
    โ”œโ”€โ”€ gildong
	โ”‚   โ””โ”€โ”€ memo.txt
    โ””โ”€โ”€ dojun
	    โ”œโ”€โ”€ game.doc
	    โ””โ”€โ”€ junk.mail

Compositeย ํŒจํ„ด์˜ ๋“ฑ์žฅ์ธ๋ฌผ

Fileย ํด๋ž˜์Šค

  • ๋‚ด์šฉ๋ฌผ์„ ๋‚˜ํƒ€๋‚ด๋Š” ์žŽย Leafย ์—ญํ• ์„ ํ•œ๋‹ค.
  • ์ด ์•ˆ์—๋Š” ๋‹ค๋ฅธ ๊ฒƒ์„ ๋„ฃ์„ ์ˆ˜ ์—†๋‹ค.

Directoryย ํด๋ž˜์Šค

  • ์žŽ ์—ญํ• ์ด๋‚˜ ๋ณตํ•ฉ์ฒด ์—ญํ• ์„ ๋„ฃ์„ ์ˆ˜ ์žˆ๋Š” ๋ณตํ•ฉ์ฒดย Compositeย ์—ญํ• ์„ ํ•œ๋‹ค.

Entryย ํด๋ž˜์Šค

  • ์žŽ ์—ญํ• ๊ณผ ๋ณตํ•ฉ์ฒด ์—ญํ• ์„ ๋™์ผ์‹œํ•˜๊ธฐ ์œ„ํ•œ ์ƒ์œ„ ํด๋ž˜์Šคย Componentย ์—ญํ• ์„ ํ•œ๋‹ค.

Mainย ํด๋ž˜์Šค

  • ํ•ด๋‹น ํŒจํ„ด์˜ ์‚ฌ์šฉ์ž์ธ ์˜๋ขฐ์žย Clientย ์—ญํ• ์„ ํ•œ๋‹ค.

์ฑ…์—์„œ ์ œ์‹œํ•˜๋Š” ํžŒํŠธ

๋ณต์ˆ˜์™€ ๋‹จ์ˆ˜ ๋™์ผ์‹œํ•˜๊ธฐ

  • Compositeย ํŒจํ„ด์€ ๊ทธ๋ฆ‡๊ณผ ๋‚ด์šฉ๋ฌผ์„ ๋™์ผ์‹œํ•˜๋Š” ํŒจํ„ด์ธ๋ฐ, ์ด๋Š” ๋ณต์ˆ˜์™€ ๋‹จ์ˆ˜๋ฅผ ๋™์ผ์‹œํ•œ๋‹ค๊ณ  ๋งํ•  ์ˆ˜ ์žˆ๋‹ค.
  • ์˜ˆ๋ฅผ ๋“ค์–ด ํ‚ค๋ณด๋“œ ์ž…๋ ฅ, ํŒŒ์ผ ์ž…๋ ฅ, ๋„คํŠธ์›Œํฌ ์ž…๋ ฅ ๋“ฑ์˜ ํ”„๋กœ๊ทธ๋žจ ๋™์ž‘ ํ…Œ์ŠคํŠธ๋ฅผ ๋ชจ์•„์„œ ํ•  ๋•Œ ํ•ด๋‹น ํŒจํ„ด์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.
  • ์ž…๋ ฅ ํ…Œ์ŠคํŠธ๋ฅผ ๋ชจ์•„ย InputTest๋ผ๋Š” ์ž…๋ ฅ ํ…Œ์ŠคํŠธ๋กœ ๋งŒ๋“ค ์ˆ˜ ์žˆ๊ณ , ๋™์ผํ•˜๊ฒŒ ์ถœ๋ ฅ ํ…Œ์ŠคํŠธ๋ฅผ ๋งŒ๋“ค ์ˆ˜ ์žˆ๋‹ค.
  • ์‹ฌ์ง€์–ดย InputOutputTest๋ผ๋Š” ์ž…์ถœ๋ ฅ ํ…Œ์ŠคํŠธ๊นŒ์ง€ ๋งŒ๋“ค ์ˆ˜ ์žˆ๋‹ค.

add๋Š” ์–ด๋””์— ๋‘์–ด์•ผ ํ• ๊นŒ?

  • ์˜ˆ์ œ ํ”„๋กœ๊ทธ๋žจ๊ณผย GoFย ์ฑ…์—์„œ๋Š”ย add,ย remove,ย getChildย ๋“ฑ ์ž์‹์„ ์กฐ์ž‘ํ•˜๋Š” ๋ฉ”์†Œ๋“œ๋ฅผ ๋ณตํ•ฉ์ฒด ์—ญํ• ์—์„œ ์ •์˜ํ•˜์˜€๋‹ค.
  • ๋งŒ์•ฝ ์žŽ ์—ญํ• ์—์„œ ์ž์‹์„ ์กฐ์ž‘ํ•˜๋Š” ์š”์ฒญ์ด ๋ฐœ์ƒํ•˜๋ฉด ์˜ค๋ฅ˜ ์ฒ˜๋ฆฌ๊ฐ€ ํ•„์š”ํ•˜๋‹ค.
  • ๊ทธ๋ ‡๋‹ค๋ฉดย Directoryย ํด๋ž˜์Šค์™€ย Entryย ํด๋ž˜์Šค ์ค‘์—์„œ๋Š” ์ž์‹์„ ์กฐ์ž‘ํ•˜๋Š” ๋ฉ”์†Œ๋“œ๋ฅผ ์–ด๋””์— ๋‘๋Š” ๊ฒƒ์ด ๋” ์ข‹์„๊นŒ?
  • ์ด๋Š” ๊ทธ๋ฆ‡๊ณผ ๋‚ด์šฉ๋ฌผ์„ ๋™์ผ์‹œํ•œ ๊ฒฐ๊ณผ๋กœ ์–ป์–ด์ง€๋Š” ๊ฒƒ์€ ๋ฌด์—‡์ธ๊ฐ€?์— ๋Œ€ํ•œ ๋Œ€๋‹ต์ด๋‹ค.
  • ๊ฒฐ๋ก ์ ์œผ๋กœ ์„ค๊ณ„์ž๋Š” ํ•ด๋‹น ํด๋ž˜์Šค๊ฐ€ ๊ฐ€์ ธ์•ผ ํ•  ์ฑ…๋ฌด๋ฅผ ๋ช…ํ™•ํžˆ ํ•ด์•ผํ•˜๋ฉฐ, ์ด๋Ÿฌํ•œ ๋ฐฉํ–ฅ์— ๋” ์ ํ•ฉํ•œ ์œ„์น˜์— ๋ฉ”์†Œ๋“œ๋ฅผ ์œ„์น˜์‹œํ‚ค๋Š” ๊ฒƒ์ด ์ ์ ˆํ•˜๋‹ค.

์žฌ๊ท€์  ๊ตฌ์กฐ๋Š” ๋ชจ๋“  ์žฅ๋ฉด์—์„œ ๋“ฑ์žฅํ•œ๋‹ค.

  • ์ผ๋ฐ˜์ ์œผ๋กœ ํŠธ๋ฆฌ ๊ตฌ์กฐ๋กœ ๋œ ๋ฐ์ดํ„ฐ ๊ตฌ์กฐ๋Š”ย Compositeย ํŒจํ„ด์— ํ•ด๋‹นํ•œ๋‹ค.
  • ๋ฌธ์žฅ์˜ ๊ธ€๋จธ๋ฆฌ ๊ธฐํ˜ธ ํ•ญ๋ชฉ ์•ˆ์— ๋‹ค์‹œ ํ•ญ๋ชฉ์ด ํฌํ•จ๋˜๋Š” ๊ฒƒ์„ ๊ทธ ์˜ˆ๋กœ ๋“ค ์ˆ˜ ์žˆ๋‹ค.
This post is licensed under CC BY 4.0 by the author.