티스토리 뷰
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
반응형
'JAVA > Design_Pattern' 카테고리의 다른 글
[Design_Pattern] 파사드 패턴 (1) | 2022.03.13 |
---|---|
[Design_Pattern] 데코레이터 패턴 (0) | 2022.03.11 |
[Design_Pattern] 어댑터 패턴 (0) | 2022.03.05 |
[Design_Pattern] 싱글톤패턴 (0) | 2022.03.01 |
[Design_Pattern] 프로토 타입 패턴 (0) | 2022.02.28 |
공지사항
최근에 올라온 글
최근에 달린 댓글
- Total
- Today
- Yesterday
TAG
- 트랜잭셔널 아웃박스 패턴 스프링 부트 예제
- spring boot redis 대기열 구현
- polling publisher spring boot
- 공간 기반 아키텍처
- @ControllerAdvice
- 자바 백엔드 개발자 추천 도서
- JDK Dynamic Proxy와 CGLIB의 차이
- java userThread와 DaemonThread
- 레이어드 아키텍처란
- space based architecture
- spring boot poi excel download
- redis 대기열 구현
- transactional outbox pattern spring boot
- pipe and filter architecture
- spring boot excel download oom
- service based architecture
- redis sorted set
- transactional outbox pattern
- spring boot redisson destributed lock
- 람다 표현식
- redis sorted set으로 대기열 구현
- spring boot redisson sorted set
- spring boot 엑셀 다운로드
- spring boot excel download paging
- 트랜잭셔널 아웃박스 패턴 스프링부트
- java ThreadLocal
- spring boot redisson 분산락 구현
- 서비스 기반 아키텍처
- pipeline architecture
- microkernel architecture
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
글 보관함