컴퍼지트 패턴을 이해한다.

Goal

  • 컴퍼지트 패턴의 개념을 이해한다.
  • 예시를 통해 컴퍼지트 패턴을 이해한다.

컴퍼지트 패턴이란

참고

예시

컴퓨터에 추가 장치 지원하기

참고

public class Keyboard {
  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 { 동일한 구조 }
public class Monitor { 동일한 구조 }
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, Monitor 객체를 생성
    Keyboard keyboard = new Keyboard(5, 2);
    Body body = new Body(100, 70);
    Monitor 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");
  }
}

[출력 결과]
Computer Price: 102만원
Computer Power: 120W

문제점

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; // 추가

  . . .
  public addMonitor(Monitor monitor) { this.monitor = monitor; } // 추가

  public int getPrice() {
    . . .
    int speakerPrice = speaker.getPrice(); // 추가
    return keyboardPrice + bodyPrice + monitorPrice + speakerPrice;
  }
  public int getPower() {
    . . .
    int speakerPower = speaker.getPower(); // 추가
    return keyboardPower + bodyPower + monitorPower + speakerPower;
  }
}

해결책

구체적인 부품들을 일반화한 클래스를 정의하고 이를 Computer 클래스가 가리키도록 설계한다.

  1. 구체적인 부품들을 일반화한 ComputerDevice 클래스를 정의
    • ComputerDevice 클래스는 구체적인 부품 클래스의 공통 기능만 가지며 실제로 존재하는 구체적인 부품이 될 수는 없다. (즉, ComputerDevice 객체를 실제로 생성할 수 없다.)
    • 그러므로 ComputerDevice 클래스는 추상 클래스가 된다.
  2. 구체적인 부품 클래스들(Keyboard, Body 등)은 ComputerDevice의 하위 클래스로 정의
  3. Computer 클래스는 복수 개( 0..* )의 ComputerDevice 객체를 갖음
  4. Computer 클래스도 ComputerDevice 클래스의 하위 클래스로 정의
    • 즉, Computer 클래스도 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 { 동일한 구조 }
public class Monitor { 동일한 구조 }
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");
  }
}

관련된 Post

References