디자인 패턴

Composite Pattern

kyoulho 2024. 5. 1. 14:06

컴포지트 패턴은 객체들을 트리구조로 구성하여 개별 객체와 객체 컬렉션을 동일하게 다루도록 하는 구조적 디자인 패턴이다.

 

컴포지트 패턴의 구성 요소

  1. Component (구성 요소):
    • 복합 객체와 개별 객체가 구현해야 하는 공통 인터페이스를 정의한다.
    • 복합 객체와 개별 객체를 동일하게 취급하기 위한 메서드들이 정의된다.
  2. Leaf (단일 객체):
    • 복합 객체의 구성 요소가 되는 개별 객체를 나타낸다.
    • Component 인터페이스를 구현하고, 자식을 가질 수 없다.
  3. Composite (복합 객체):
    • Leaf나 다른 Composite 객체를 자식으로 가질 수 있는 객체를 나타낸다.
    • Component 인터페이스를 구현하면서 자식 객체를 관리하는 메서드들이 정의된다.
    • 컴포지트 패턴의 예시로 그래픽 객체를 다루는 시스템을 생각해볼 수 있다. 여러 도형이나 텍스트를 단일 객체로 취급하면서도 각각은 개별 객체로서 행동할 수 있다.

 

컴포지트 패턴과 단일 역할 원칙

컴포지트 패턴은 한 클래스에서 여러가지 역할을 한다. 이는 단일 역할 원칙을 깨는 대신 투명성을 확보하는 패턴이라고 할 수 있다.

 

예제

// Component: 모든 구성요소의 공통 인터페이스
public abstract class Employee {
    // 자신의 역할에 맞지 않는 메소드는 오버라이드 하지 않고 기본 구현을 그대로 사용
    String getName() {
        throw new UnsupportedOperationException();
    }

    double getSalary() {
        throw new UnsupportedOperationException();
    }

    public void addEmployee(Employee employee) {
        throw new UnsupportedOperationException();
    }
}

// Composite: 부서를 나타내는 클래스
class Department extends Employee {
    private final String name;
    private final List<Employee> employees = new ArrayList<>();

    public Department(String name) {
        this.name = name;
    }

    public void addEmployee(Employee employee) {
        employees.add(employee);
    }

    @Override
    public String getName() {
        return name;
    }

    @Override
    public double getSalary() {
        double totalSalary = 0;
        for (Employee employee : employees) {
            totalSalary += employee.getSalary();
        }
        return totalSalary;
    }
}

// Leaf: 개별 직원을 나타내는 클래스
class Worker extends Employee {
    private final String name;
    private final double salary;

    public Worker(String name, double salary) {
        this.name = name;
        this.salary = salary;
    }

    @Override
    public String getName() {
        return name;
    }

    @Override
    public double getSalary() {
        return salary;
    }
}

// Client: 컴포지트 패턴을 활용하는 클라이언트 코드
public class Organization {
    public static void main(String[] args) {
        Employee worker1 = new Worker("John Doe", 50000);
        Employee worker2 = new Worker("Jane Smith", 60000);

        Employee development = new Department("Development");
        development.addEmployee(worker1);
        development.addEmployee(worker2);

        Employee worker3 = new Worker("Alice Johnson", 55000);
        Employee worker4 = new Worker("Bob Williams", 52000);

        Employee marketing = new Department("Marketing");
        marketing.addEmployee(worker3);
        marketing.addEmployee(worker4);

        Employee company = new Department("Company");
        company.addEmployee(development);
        company.addEmployee(marketing);

        // 각 부서와 직원의 연봉의 총합을 계산
        System.out.printf("Total Salary of %s: %f%n", development.getName(), development.getSalary());
        System.out.printf("Total Salary of %s: %f%n", marketing.getName(), marketing.getSalary());
        System.out.printf("Total Salary of %s: %f%n", company.getName(), company.getSalary());
    }
}

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

Facade Pattern  (0) 2024.05.12
Decorator Pattern  (0) 2024.05.05
Command Pattern  (0) 2024.04.28
Chain Of Responsibility Pattern  (0) 2024.04.27
Bridge Pattern  (0) 2024.04.10