컴퍼지트 패턴
컴퍼지트 패턴은 전체에 부분을 이루는 객체들을 자료구조를 통해 저장하여, 전체 클래스 코드를 바꾸지 않고도 부분에 해당하는 객체들을 추가나 삭제 할 수 있다. 부분-전체 관계를 갖는 객체들을 정의할 때 유용하다.
•
Composite : 복수 개의 Component를 갖도록 정의하는 전체 클래스
•
Component : Leaf 클래스와 전체에 해당하는 Composite 클래스의 공통 인터페이스
•
Leaf : 부분에 대한 구체 클래스이자 Composite의 부품
컴퍼지트 패턴을 순차 다이어그램으로 표현하면 이와 같다.
컴퓨터 부품 예제로 컴포지트 패턴 이해하기
컴퓨터 부품 예제
컴퓨터를 키보드, 본체, 모니터로 모델링하면 이와 같이 할 수 있다.
public class Body {
private int price;
private int power;
public Body(final int price, final int power) {
this.price = price;
this.power = power;
}
public int getPrice() {
return price;
}
public int getPower() {
return power;
}
}
Java
복사
public class Keyboard {
private int price;
private int power;
public Keyboard(final int price, final int power) {
this.price = price;
this.power = power;
}
public int getPrice() {
return price;
}
public int getPower() {
return power;
}
}
Java
복사
public class Monitor {
private int price;
private int power;
public Monitor(final int price, final int power) {
this.price = price;
this.power = power;
}
public int getPrice() {
return price;
}
public int getPower() {
return power;
}
}
Java
복사
public class Computer {
private Body body;
private Monitor monitor;
private Keyboard keyboard;
public Computer(final Body body, final Monitor monitor, final Keyboard keyboard) {
this.body = body;
this.monitor = monitor;
this.keyboard = keyboard;
}
public int getPrice() {
int price = 0;
price += body.getPrice();
price += monitor.getPrice();
price += keyboard.getPrice();
return price;
}
public int getPower() {
int power = 0;
power += body.getPower();
power += monitor.getPower();
power += keyboard.getPower();
return power;
}
}
Java
복사
public class Client {
public static void main(String[] args) {
final Body body = new Body(100, 70);
final Monitor monitor = new Monitor(20, 30);
final Keyboard keyboard = new Keyboard(5, 2);
final Computer computer = new Computer(body, monitor, keyboard);
final int power = computer.getPower();
final int price = computer.getPrice();
System.out.println("power = " + power);
System.out.println("price = " + price);
}
}
Java
복사
이를 코드로 나타내면 위와 같다.
문제점
만약 이렇게 모델링된 컴퓨터에 Speaker라는 부품을 추가하는 경우에는
public class Computer {
private Body body;
private Monitor monitor;
private Keyboard keyboard;
private Speaker speaker;
public Computer(final Body body, final Monitor monitor, final Keyboard keyboard, final Speaker speaker) {
this.body = body;
this.monitor = monitor;
this.keyboard = keyboard;
this.speaker = speaker;
}
public int getPrice() {
int price = 0;
price += body.getPrice();
price += monitor.getPrice();
price += keyboard.getPrice();
price += speaker.getPrice();
return price;
}
public int getPower() {
int power = 0;
power += body.getPower();
power += monitor.getPower();
power += keyboard.getPower();
power += speaker.getPower();
return power;
}
}
Java
복사
이처럼 Computer 클래스의 코드 변경이 발생하게 되어 OCP를 위반하게 된다.
해결책
이 문제를 컴포지트 패턴을 통해 해결할 수 있다.
이처럼 ComputerDevice라는 인터페이스를 두어 컴퓨터 부품들을 추상화하고, Computer 클래스 내부에 ComputerDevice 자료구조를 두어 확장 가능하도록 구현하는 것이다.
public class Body implements ComputerDevice {
...
}
public class Monitor implements ComputerDevice {
...
}
public class Keyboard implements ComputerDevice {
...
}
Java
복사
public class Computer implements ComputerDevice {
private List<ComputerDevice> computerDevices;
public Computer(final List<ComputerDevice> computerDevices) {
this.computerDevices = computerDevices;
}
public int getPrice() {
return computerDevices.stream()
.mapToInt(ComputerDevice::getPrice)
.sum();
}
public int getPower() {
return computerDevices.stream()
.mapToInt(ComputerDevice::getPower)
.sum();
}
}
Java
복사
public class Client {
public static void main(String[] args) {
final Body body = new Body(100, 70);
final Monitor monitor = new Monitor(20, 30);
final Keyboard keyboard = new Keyboard(5, 2);
final Computer computer = new Computer(List.of(body, monitor, keyboard));
final int power = computer.getPower();
final int price = computer.getPrice();
System.out.println("power = " + power);
System.out.println("price = " + price);
}
}
Java
복사
이렇게 설계하면 Speaker 클래스를 추가하는 경우에도,
public class Client {
public static void main(String[] args) {
final Body body = new Body(100, 70);
final Monitor monitor = new Monitor(20, 30);
final Keyboard keyboard = new Keyboard(5, 2);
final Speaker speaker = new Speaker(10, 10);
final Computer computer = new Computer(List.of(body, monitor, keyboard, speaker));
final int power = computer.getPower();
final int price = computer.getPrice();
System.out.println("power = " + power);
System.out.println("price = " + price);
}
}
Java
복사
이와 같이 Computer 클래스의 변경 없이도 확장 가능해진다.