해당 포스트는 "자바 객체지향 디자인 패턴", "JAVA 언어로 배우는 디자인 패턴 입문" 책의 내용을 요약한 것이다.



※컴퍼지트(Composite) 패턴

: 전체-부분의 관계를 갖는 객체들 사이의 관계를 정의할 때 유용하다. 클라이언트는 전체와 부분을 구분하지 않고 동일한 인터페이스를 사용할 수 있다. 또한 부분 객체의 추가나 삭제 등이 있어도 전체 객체의 클래스 코드를 변경하지 않아도 된다.

 

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

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 {
   private int price;
   private int power;
  
   public Body(int power, int price){
         this.power = power;
         this.price = price;
   }
   public int getPrice(){
        return price;
   }
   public int getPower(){
       return power;
   }
}

public class Monitor {
   private int price;
   private int power;
  
   public Monitor(int power, int price){
         this.power = power;
         this.price = price;
   }
   public int getPrice(){
        return price;
   }
   public int getPower(){
       return power;
   }
}
public class Computer{
   private Body body;
   private Keyboard keyboard;
   private Monitor monitor;
  
   public void addBody(Body body){
      this.body = body;
   }
   public void addKeyboard(Keyboard keyboard){
     this.keyboard = keyboard;
   }
   public void addMonitor(Monitor monitor){
      this.monitor = monitor;
   }

   public int getPrice(){
       return body.getPrice()+keyboard.getPrice()+monitor.getPrice();
   }
   public int get Power(){
     return body.getPower() + keyboard.getPower() + monitor.getPower();
   }
}

위 예젤르 보면 Computer 클래스는 Keyboard, Body, Monitor 객체를 참조한다. 즉 Computer 객체는 전체, 나머지 부품 객체는 부분이라고 할 수 있다. 또한 이들 과의 관계는 현재 합성관게이다.

 

 

- 문제점

만약 Computer 클래스의 부품으로 Speaker 클래스를 와Mouse 클래스를 추가한다면 Speaker와 Mouse 객체를 만든 후에 Computer 클래스에서 따로 add 메서드를 만들어서 속성값으로 참조하도록 수정해야 한다. 또한, Computer 클래스의 getPrice()와 getPower() 메서드를 수정해야한다. 즉, 부품을 추가하면 Computer 클래스를 수정해야하고 이는 OCP를 위반하는 것이다. 이렇게, 전체-부분 관계에서 이러한 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.price = price;
      this.power = power;
   }
   public int getPrice(){
     return price;
   }
   public int getPower(){
     return power;
   }
}

ComputerDevice 추상 클래스를 만들어 각각의 부품 객체에서 ComputerDevice 클래스를 상속받게 한다.


public class Computer extends ComputerDevice { private List<ComputerDevice> components = new ArrayList<ComputerDevice>(); public void addComponent(ComputerDevice component){ components.add(component); } public void 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) power += component.getPower(); return power; } }

Computer 클래스도 마찬가지로 ComputerDevice 추상클래스를 상속받게 했고 부품 객체들은 List 콜렉션에서 관리된다.



public class Client{
  public static void main(String[] args){
    Body body = new Body(100,40);
    Keyboard keyboard = new Keyboard(50,90);
    Monitor monitor = new Monitor(40,20);

    Computer computer = new Computer();
    computer.addComponent(body);
    computer.addComponent(keyboard);
    computer.addComponent(monitor);
    
    System.out.println(computer.getPrice()+"-"computer.getPower());
  }
}

메인 위와 같다. 만약 여기서 Speaker와 Mouse 부품이 추가 될시 단지 ComputerDevice 클래스를 상속받은 클래스만 추가하고 메인만 추가해주면 된다. Computer 클래스는 수정 없이 부품들의 추가가 가능해 Computer 클래스는 OCP를 준수할 수 있게 된다.





'자바 > 디자인패턴' 카테고리의 다른 글

퍼사드 패턴  (0) 2017.06.08
프로토타입 패턴  (0) 2017.06.08
데코레이터(Decorator) 패턴  (0) 2017.06.06
옵저버(Observer) 패턴(2) - 직접 구현  (0) 2017.06.06
옵저버(Observer) 패턴(1) - JDK API 활용  (0) 2017.06.06

+ Recent posts