JAVA/Design_Pattern
[Design_Pattern] 컴포지트 패턴
realizers
2022. 3. 7. 22:07
728x90
반응형
컴포지트 패턴
- 여러개의 객체들로 구성된 복합 객체와 단일 객체를 클라이언트에서 구별없이 다루게 해주는 패턴입니다.
- 클라이언트는 복합 객체와 단일 객체를 신경쓰지 않고 인터페이스를 통해 어떠한 객체든 사용할 수 있습니다.
클래스 다이어 그램
Component
- Leaf 클래스와 Composite 클래스의 공통 인터페이스 정의
Leaf
- 구체적인 부분 클래스
- Composite 객체의 부품으로 설정
Composite
- 전체 클래스
- 복수개의 Component를 갖도록 정의
예시
휴대폰에 각종 기능 장착하기
// 배터리 기능
@Getter
public class Battery {
private int price;
private int power;
public Battery(int price, int power) {
this.price = price;
this.power = power;
}
}
// 저장 용량 기능
@Getter
public class StorageCapacity {
private int price;
private int power;
public StorageCapacity(int price, int power) {
this.price = price;
this.power = power;
}
}
// 플래쉬 기능
@Getter
public class Flash {
private int price;
private int power;
public Flash(int price, int power) {
this.price = price;
this.power = power;
}
}
public class SmartPhone {
private Battery battery;
private StorageCapacity storageCapacity;
private Flash flash;
public void addBattery(Battery battery) {
this.battery = battery;
}
public void addStorageCapacity(StorageCapacity storageCapacity) {
this.storageCapacity = storageCapacity;
}
public void addFlash(Flash flash) {
this.flash = flash;
}
public int getPrice(){
return battery.getPrice() + storageCapacity.getPrice() + flash.getPrice();
}
public int getPower() {
return battery.getPower() + storageCapacity.getPower() + flash.getPower();
}
}
public class Client {
public static void main(String[] args) {
Battery battery = new Battery(100000, 50);
StorageCapacity storageCapacity = new StorageCapacity(150000, 60);
Flash flash = new Flash(200000, 80);
SmartPhone smartPhone = new SmartPhone();
smartPhone.addBattery(battery);
smartPhone.addStorageCapacity(storageCapacity);
smartPhone.addFlash(flash);
int smartPhonePrice = smartPhone.getPrice();
int smartPhonePower = smartPhone.getPower();
System.out.println("SmartPhone Price = " + smartPhonePrice + "원");
// SmartPhone Price = 450000원
System.out.println("SmartPhone Power = " + smartPhonePower + "W");
// SmartPhone Power = 190W
}
}
상황 : 여기서 다른 부품이 추가되어야한다면?
- 현재 위와 같은 구조로 카메라와 스피커의 기능이 추가된다면 어떻게 될까?
// 추가되는 기능
@Getter
public class Camera {
private int price;
private int power;
public Camera(int price, int power) {
this.price = price;
this.power = power;
}
}
// 추가되는 기능
@Getter
public class Speaker {
private int price;
private int power;
public Speaker(int price, int power) {
this.price = price;
this.power = power;
}
}
public class SmartPhone {
...
/**
* 추가되는 기능
*/
private Camera camera;
private Speaker speaker;
...
/**
* 추가되는 기능
*/
public void addCamera(Camera camera) {
this.camera = camera;
}
public void addSpeaker(Speaker speaker) {
this.speaker = speaker;
}
public int getPrice(){
return battery.getPrice() +
storageCapacity.getPrice() +
flash.getPrice() +
camera.getPrice() +
speaker.getPrice();
}
public int getPower() {
return battery.getPower() +
storageCapacity.getPower() +
flash.getPower() +
camera.getPower() +
speaker.getPower();
}
}
public class Client {
public static void main(String[] args) {
Battery battery = new Battery(100000, 50);
StorageCapacity storageCapacity = new StorageCapacity(150000, 60);
Flash flash = new Flash(200000, 80);
Camera camera = new Camera(300000, 80);
Speaker speaker = new Speaker(500000, 80);
SmartPhone smartPhone = new SmartPhone();
smartPhone.addBattery(battery);
smartPhone.addStorageCapacity(storageCapacity);
smartPhone.addFlash(flash);
smartPhone.addCamera(camera);
smartPhone.addSpeaker(speaker);
int smartPhonePrice = smartPhone.getPrice();
int smartPhonePower = smartPhone.getPower();
System.out.println("SmartPhone Price = " + smartPhonePrice + "원");
// SmartPhone Price = 1250000원
System.out.println("SmartPhone Power = " + smartPhonePower + "W");
// SmartPhone Power = 350W
}
}
문제점
- 위 상황의 문제점은 새로운 부품이 추가될 때 마다 SmartPhone 클래스를 계속하여 수정을 해야합니다.
- SmartPhone 클래스에 속한 여러 구체적인 객체들을 가리키게되면 OCP원칙을 위반하게 됩니다.
해결책
- 구체적인 부품들을 일반화한 클래스를 정의하고 이를 SmartPhone 클래스가 가리키도록합니다.
Component의 역할을 하는 클래스
public interface SmartPhoneDevice {
int getPrice();
int getPower();
}
Leaf의 역할을 하는 클래스
// 배터리 기능
public class Battery implements SmartPhoneDevice {
private int price;
private int power;
public Battery(int price, int power) {
this.price = price;
this.power = power;
}
@Override
public int getPrice() {
return this.price;
}
@Override
public int getPower() {
return this.power;
}
}
... Camera, Flash, Speaker, StorageCapacity의 역할을 하는 기능 동일
Composite의 역할을 하는 클래스
public class SmartPhone implements SmartPhoneDevice{
private List<SmartPhoneDevice> components = new ArrayList<>();
public void addComponent(SmartPhoneDevice component) {
components.add(component);
}
public void removeComponent(SmartPhoneDevice component) {
components.remove(component);
}
@Override
public int getPrice() {
return components.stream().mapToInt(SmartPhoneDevice::getPrice).sum();
}
@Override
public int getPower() {
return components.stream().mapToInt(SmartPhoneDevice::getPower).sum();
}
}
Client
public class Client {
public static void main(String[] args) {
SmartPhoneDevice battery = new Battery(100000, 50);
SmartPhoneDevice storageCapacity = new StorageCapacity(150000, 60);
SmartPhoneDevice flash = new Flash(200000, 80);
SmartPhoneDevice camera = new Camera(300000, 80);
SmartPhoneDevice speaker = new Speaker(500000, 80);
SmartPhone smartPhone = new SmartPhone();
smartPhone.addComponent(battery);
smartPhone.addComponent(storageCapacity);
smartPhone.addComponent(flash);
smartPhone.addComponent(camera);
smartPhone.addComponent(speaker);
int smartPhonePrice = smartPhone.getPrice();
int smartPhonePower = smartPhone.getPower();
System.out.println("SmartPhone Price = " + smartPhonePrice + "원");
// SmartPhone Price = 1250000원
System.out.println("SmartPhone Power = " + smartPhonePower + "W");
// SmartPhone Power = 350W
}
}
728x90
반응형