컴퍼지트 패턴 (Composite pattern)
JAVA/Design Pattern

컴퍼지트 패턴 (Composite pattern)

반응형

컴포지트 패턴 (Composite pattern)은 부분-전체의 관계를 갖는 객체들을 정의할 때 유용하다.

그리고 클라이언트는 전체와 부분을 구분하지 않고 동일한 인터페이스를 사용할 수 있다,

컴퍼지트 패턴은 크게 다음과 같이 구성된다.

Component : Leaf 클래스와 Composite 클래스에 공통 인터페이스
Leaf: 부품들 (Component 클래스의 하위 클래스)
Composite : 부품들을 사용하는 본체 클래스 여러가지 Leaf 클래스들을 가진다. 또한 Composite 클래스 역시 Component의 하위 클래스로서 여러개의 Composite를 소유할 수도 있다.





예를 들어보자

휴대폰을 조립하기 위해서
다음과 같이 휴대폰을 구성하기위해

부품들의 가격과 전력을 계산하는 구조가 있다고 가정해보자.

Cellphone 클래스는 자신의 부품들을 has a 관계로 가지고 있으며,
전력과 가격을 구하기 위해서 각 부품들의 가격과 전력을 각각 가져와서 구한다.


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
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
public class Cpu {
    private int price;
    private int power;
    
    public Cpu(int price, int power) {
        this.price = price;
        this.power = power;
    }
    
    public int getPrice() {
        return price;
    }
 
    public void setPrice(int price) {
        this.price = price;
    }
 
    public int getPower() {
        return power;
    }
 
    public void setPower(int power) {
        this.power = power;
    }
 
}
 
 
public class Memory {
    private int price;
    private int power;
 
    public Memory(int price, int power) {
        this.price = price;
        this.power = power;
    }
 
    public int getPrice() {
        return price;
    }
 
    public void setPrice(int price) {
        this.price = price;
    }
 
    public int getPower() {
        return power;
    }
 
    public void setPower(int power) {
        this.power = power;
    }
 
}
 
public class CellPhone extends Component {
    private Cpu cpu;
    private Memory memory;
 
    public int getPrice() {
        return cpu.getPrice() + memory.getPrice();
    }
 
    public int getPower() {
        return cpu.getPower() + memory.getPower();
    }
 
    public Cpu getCpu() {
        return cpu;
    }
 
    public void setCpu(Cpu cpu) {
        this.cpu = cpu;
    }
 
    public Memory getMemory() {
        return memory;
    }
 
    public void setMemory(Memory memory) {
        this.memory = memory;
    }
 
}
cs



하지만 이런경우에는

새로운 부품이 추가될 경우에
CPU, MEMORY와 같이 추가된 부품을 CellPhone 클래스에 추가하고 

getPrice(), getPower()메서드를 수정한다.

하지만 이런경우에는 굉장히 번거롭고 OCP를 위반한다.

[컴퍼지트 패턴을 이용한 해결방법]

새로운 부품이 추가되어도 기존의 getPrice(), getPower() 메소드의 변경이
없이 동작할 수있도록 부품들을 Component 추상 클래스를 상속하게 한 후

이런 Component들을 여러개 소지할 수 있도록 Cellphone을 변경한다.



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
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
package compisite;
 
import java.util.List;
 
public class CellPhone {
    private List<Component> components;
 
    public int getPrice() {
        int price = 0;
        for (Component component : components) {
            price += component.getPrice();
        }
        return price;
    }
 
    public int getPower() {
        int power = 0;
        for (Component component : components) {
            power += component.getPrice();
        }
        return power;
    }
    
    public void addComponent(Component component) {
        components.add(component);
    }
    
    public void delComponent(Component component) {
        components.remove(component);
    }
}
 
package compisite;
 
public abstract class Component {
    abstract int getPrice();
    abstract int getPower();
 
}
 
package compisite;
 
public class Cpu extends Component {
    private int price;
    private int power;
    
    public Cpu(int price, int power) {
        this.price = price;
        this.power = power;
    }
    
    @Override
    public int getPrice() {
        return price;
    }
 
    public void setPrice(int price) {
        this.price = price;
    }
    
    @Override
    public int getPower() {
        return power;
    }
 
    public void setPower(int power) {
        this.power = power;
    }
 
}
package compisite;
 
public class Memory extends Component {
    private int price;
    private int power;
 
    public Memory(int price, int power) {
        this.price = price;
        this.power = power;
    }
 
    @Override
    public int getPrice() {
        return price;
    }
 
    public void setPrice(int price) {
        this.price = price;
    }
 
    @Override
    public int getPower() {
        return power;
    }
 
    public void setPower(int power) {
        this.power = power;
    }
 
}
cs




이렇게 변경하게 되면 새로운 부품이 추가되어도 
기존의 메소드를 변경해야하는 작업이 없어진다.


이 예제에서
Component는 Component 추상클래스
Leaf는 Cpu, Memory 클래스
Composite는 CellPhone 클래스이다.

여러 공통 클래스들을 소유하면서 그 공통 클래스들의
속성을 뽑아내어 동일한 동작을 해야하는 경우에는 컴포지트 패턴을 사용하면 좋다.

출처 : JAVA 객체지향 디자인 패턴 한빛 미디어

반응형