본문 바로가기

Java

디자인 패턴5 - 컴포지트 패턴 ( Composite pattern )

디자인패턴5 - 컴포지트 패턴 (Composite pattern )

이것도 단어 뜻을 그대로 살펴보면 composite(복합물) 패턴? 또 뭔가 조합을 하는 패턴인 것 같다.

사용자(클라이언트)가 어떠한 조합으로 생성 된 클래스를 동일하게 사용할 때 쓰는 패턴이다.

말만 보면 항상 와닿지 않는다.

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


만약에 다른 부품이 추가된다면?


1. 컴퓨터 객체에 새로운 부품을 추가하는 코드 생성

2. 클라이언트에서 새로운 부품 생성 + 컴퓨터에 조합하는 코드 추가

3. 새로운 부품과 관련된 클래스 추가


컴퓨터는 동작이 바뀌지도 않는데 수정이 필요하게 되엇다. 심지어 컴퓨터는 구체적인 부품 구현체를 가르키고 있기 때문에 OCP를 위반하고 있는 코드이다.


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");

  }

}


이제 Computer 클래스는 OCP를 준수하게 되었다. 장치가 추가되더라도 Computer 코드는 수정을 하지 않아도 된다. 


Decorator 패턴이랑 뭔가 비슷한데??

둘다 객체를 조직화 하기 위해서 사용된다는 점은 같다.

Decorator 패턴

상속없이 객체에 새로운 서비스를 추가하고 싶을 때 

Composite 패턴

관련된 객체 ( 컴퓨터 부품 ) 들을 하나의 인터페이스로 다루어 일관성을 부여할 것인가 

즉 여러 개의 객체를 하나의 객체로 통일 시키고 싶은 것이다.

그래도 뭔가 정확한 차이는 모르겠다....

3

참고 : http://www.incodom.kr/%EC%BB%B4%ED%8F%AC%EC%A7%80%ED%8A%B8_%ED%8C%A8%ED%84%B4

https://gmlwjd9405.github.io/2018/08/10/composite-pattern.html