2021. 1. 20. 11:24ㆍ2021/JOB DA STUDY
Composite Pattern
여러개의 객체들로 구성된 복합 객체와 단일 객체를 클라이언트에서 구별없이 다루게 해주는 패턴
- 전체 - 부분(Directory-File) 관계를 갖는 객체들 사이의 관계 정의시 유용
- 클라이언트는 전체와 부분을 구분하지 않고, 동일한 인터페이스를 사용
- Component
- 구체적인 부분
- Leaf 클래스와 전체에 해당하는 Composite 클래스에 공통 인터페이스 정의
- Leaf
- 구체적인 부분 클래스
- Composite 객체의 부품으로 설정
- Composite
- 전체 클래스
- 복수 개의 Component를 갖도록 정의 (복수 개의 Leaf, 복수 개의 Composite 객체를 부분으로 가질 수 있다.)
컴퓨터에 추가 장치 지원하기
- Computer 클래스: 합성 관계
- Keyboard 클래스: 데이터 입력 받음
- Body 클래스: 데이터 처리
- Monitor 클래스: 처리 결과 출력
합성관계
- 생성자에서 필드에 대한 객체를 생성하는 경우
- 전체 객체의 라이프 타임과 부분 객체의 라이프 타임은 의존적 (전체 객체가 없어지면, 부분 객체도 없어진다.)
public class Keyboard{
private int price;
private int power;
public Keyboard(int power, int price){
this.price = price;
this.power = power;
}
public int getPrice() {return price;}
public int getPower() {return power;}
}
public class Body{
private int price;
private int power;
public Keyboard(int power, int price){
this.price = price;
this.power = power;
}
public int getPrice() {return price;}
public int getPower() {return power;}
}
public class Monitor{
private int price;
private int power;
public Keyboard(int power, int price){
this.price = price;
this.power = power;
}
public int getPrice() {return price;}
public int getPower() {return power;}
}
public class Computer{
private Keyboard Keyboard;
private Body body;
private Monitor monitor;
public addKeyboard(Keyboard keyboard) { this.keyboard = keyboard; }
public addBody(Body body) { this.body = body; }
public addMonitor(Monitor monitor) { this.monitor = monitor; }
public int getPrice(){
int keyboardPrice = keyboard.getPrice();
int bodyPrice = body.getPrice();
int monitorPrice = monitor.getPrice();
return keyboardPrice + bodyPrice + monitorPrice;
}
public int getPower(){
int keyboardPower = keyboard.getPower();
int bodyPower = body.getPower();
int monitorPower = monitor.getPower();
return keyboardPower + bodyPower + monitorPower;
}
}
public class Client{
public static void main(String[] args){
//컴퓨터의 부품으로 Keyboard, Body, Motitor 객체를 생성
Keyboard keyboard = new Keyboard(5, 2);
Body body = new Body(100, 70);
Moditor monitor = new Monitor(20, 30);
//Computer 객체를 생성하고, 부품 객체를 설정
Computer computer = new Computer();
computer.addKeyboard(keyboard);
computer.addBody(body);
computer.addMonitor(monitor);
//컴퓨터의 가격과 전력 소비량 구하기
int computerPrice = computer.getPrice();
int computerPower = computer.getPower();
System.out.println("Computer Price" + computerPrice + "만원");
System.out.println("Computer Power" + computerPower + "W");
}
}
문제점
- 다름 부품이 추가되는 경우
public class Speaker{
private int price;
private int power;
public Speaker(int power, int price){
this.power = power;
this.price = price;
}
public int getPrice() { return price; }
public int getPower() { return power; }
}
public class Computer{
private Speaker speaker; //추가
private Keyboard Keyboard;
private Body body;
private Monitor monitor;
public addSpeaker(Speaker speaker) { this.speaker = speaker; } //추가
public addKeyboard(Keyboard keyboard) { this.keyboard = keyboard; }
public addBody(Body body) { this.body = body; }
public addMonitor(Monitor monitor) { this.monitor = monitor; }
public int getPrice(){
int speakerPrice = speaker.getPrice(); //추가
int keyboardPrice = keyboard.getPrice();
int bodyPrice = body.getPrice();
int monitorPrice = monitor.getPrice();
return speakerPrice + keyboardPrice + bodyPrice + monitorPrice;
}
public int getPower(){
int speakerPower = speaker.getPower();
int keyboardPower = keyboard.getPower();
int bodyPower = body.getPower();
int monitorPower = monitor.getPower();
return speakerPower + keyboardPower + bodyPower + monitorPower;
}
}
*** 위와 같은 방식의 설계는 확장성이 좋지 않다. 따라서 OCP를 만족하지 않는다. ***
새로운 부품 추가가 있을 때 마다
- 새로운 부품에 대한 참조를 필드로 추가
- 새로운 부품 객체를 설정하는 setter 메서드로 addDevice와 같은 메서드 추가
- getPrice, getPower 등과 같은 컴퓨터의 부품을 이용하는 모든 메서드에서는 새롭게 추가된 부품 객체를 이용할 수 있도록 수정
해결책
- ComputerDevice 클래스
- ComputerDevice 클래스는 구체적인 부품 클래스의 '공통 기능'만 가지며, 실제 존재하는 구체적인 부품은 될 수 없다.
- ComputerDevice 객체를 실제로 생성할 수 없으므로 ComputerDevice 클래스는 추상 클래스가 된다.
- 구체적인 부품 클래스 (Keyboard, Body, Monitor, Speaker)
- ComputerDevice 클래스의 하위 클래스
- Computer 클래스
- Computer 클래스는 복수 개의 ComputerDevice 객체를 갖는다.
- ComputerDevice 클래스의 하위 클래스
- ComputerDevice 클래스를 이용하면 Client 프로그램은 Keyboard, Body 등 처럼 Computer 이용 가능
public abstract class ComputerDevice{
public abstract int getPrice();
public abstract int getPower();
}
public class Keyboard extends ComputerDevice{
private int price;
private int power;
public Keyboard(int power, int price){
this.power = power;
this.price = price;
}
public int getPrice() { return price; }
public int getPower() {return power; }
}
public class Body extends ComputerDevice{
private int price;
private int power;
public Keyboard(int power, int price){
this.power = power;
this.price = price;
}
public int getPrice() { return price; }
public int getPower() {return power; }
}
public class Monitor extends ComputerDevice{
private int price;
private int power;
public Keyboard(int power, int price){
this.power = power;
this.price = price;
}
public int getPrice() { return price; }
public int getPower() {return power; }
}
public class Computer extends ComputerDevice{
//복수 개의 ComputerDevice 객체를 가리킴
private List<ComputerDevice> components = new ArrayList<ComputerDevice>();
//ComputerDevice 객체를 Computer 클래스에 추가
public addComponent(ComputerDevice component) { components.add(component); }
//ComputerDevice 객체를 Computer 클래스에서 제거
public removeComponent(ComputerDevice component) { components.remove(component); }
//전체 가격을 포함하는 각 부품의 가격을 합산
public int getPrice(){
int price =0;
for(ComputerDevice component : components){
price += component.getPrice();
}
return price;
}
//전체 소비 전력량을 포함하는 각 부품의 소비 전력량을 합산
public int getPower(){
int power =0;
for(ComputerDevice component : components){
price += component.getPower();
}
return power;
}
}
public class Client{
public static void main(String[] args){
//컴퓨터의 부품으로 Keyboard, Body, Monitor 객체를 생성
Keyboard keyboard = new Keyboard(5, 2);
Body body = new Body(100, 70);
Monitor monitor = new Monitor(20, 30);
//Computer 객체를 생성하고, addComponent()를 통해 부품 객체들을 생성
Computer computer = new Computer();
computer.addComponent(keyboard);
computer.addComponent(body);
computer.addComponent(monitor);
//컴퓨터의 가격과 전력 소비량을 구함
int computerPrice = computer.getPrice();
int computerPower = computer.getPower();
System.out.println("Computer Price" + computerPrice + "만원");
System.out.println("Computer Power" + computerPower + "W");
}
}
- Computer Class
- ComputerDevice의 하위 클래스이면서, 복수 개의 ComputerDevice를 갖도록 설계
- addComponent() 메서드를 통해 구체적인 부품인 Keyboard, Body 등을 Computer 클래스의 부품으로 설정
- Client Class
- addComponent() 메서드를 통해 부품의 종류에 관계없이 동일한 메서드로 부품 추가
*** Computer Class는 OCP를 준수한다. ***
새로운 부품을 추가하면 ComputerDevice 클래스의 하위 클래스로 구현
Composite Pattern을 이용하면, 부분 객체의 추가/삭제 등이 있어도 전체 객체의 클래스 코드를 변경하지 않아도 된다. 따라서 전체 - 부분 관계를 갖는 객체들 사이의 관계를 정의할 때 유용하다.
'2021 > JOB DA STUDY' 카테고리의 다른 글
3주차 강의: 통계 및 머신러닝 (0) | 2021.04.28 |
---|---|
2주차 강의: 데이터 사이언스의 핵심 개념과 기술 (0) | 2021.04.26 |
디자인패턴_Factory Method Pattern of Creational Pattern (0) | 2021.01.19 |
디자인패턴_Decorator Pattern of Structural Pattern (0) | 2021.01.19 |
디자인패턴_Observer Pattern of Behavioral Pattern (0) | 2021.01.15 |