소프트웨어 디자인 패턴 - 5. PAC 패턴 (Presentation-Abstraction-Control)

2025. 1. 20. 12:33소프트웨어/디자인 패턴

PAC 패턴이란?

PAC(Presentation-Abstraction-Control) 패턴은 애플리케이션을 Presentation, Abstraction, Control의 세 가지 계층으로 분리하여 설계하는 소프트웨어 디자인 패턴입니다. 이 패턴은 특히 복잡한 시스템을 계층적으로 나누어 높은 모듈화와 재사용성을 제공하는 데 적합합니다. 각 PAC 단위는 독립적으로 동작하며 느슨하게 결합되어 있어 복잡한 시스템에서도 유지보수와 확장이 용이합니다.


구성 요소

1. Presentation

  • 사용자 인터페이스(UI)와 입력 처리 담당.
  • 사용자의 요청을 Control로 전달하고, 데이터를 화면에 표시.

2. Abstraction

  • 데이터 처리와 비즈니스 로직 담당.
  • Control에서 전달받은 데이터를 처리하고 결과를 반환.

3. Control

  • Presentation과 Abstraction 간의 흐름을 제어.
  • 사용자 입력을 해석하고, Abstraction에 데이터를 전달하며, 결과를 Presentation으로 전달.

PAC의 특징

  1. 계층적 구조:
    • 여러 PAC 단위를 계층적으로 구성하여 복잡한 시스템을 효율적으로 관리.
  2. 독립성과 느슨한 결합:
    • 각 PAC 단위는 독립적으로 동작하며 다른 단위와 느슨하게 결합.
  3. 모듈화와 재사용성:
    • 계층적으로 나뉜 구조로 인해 코드 재사용성과 유지보수가 용이.

장점

  1. 복잡한 시스템 관리 용이:
    • 계층적으로 나누어 각 부분을 독립적으로 설계 가능.
  2. 높은 모듈화:
    • 각 PAC 단위가 독립적으로 동작하여 재사용성 증가.
  3. 확장성:
    • 새로운 기능 추가 시 특정 PAC 단위만 확장하거나 추가 가능.

단점

  1. 구현 복잡성 증가:
    • 각 PAC 단위 간의 데이터 흐름을 설계하고 관리하는 데 추가적인 작업 필요.
  2. 초기 설계 비용:
    • 계층적 구조 설계와 PAC 단위 간의 책임 정의에 많은 시간 소요.

적용 예시

1. 채팅 애플리케이션

  • Presentation: 사용자 인터페이스(UI), 메시지 입력 및 출력.
  • Abstraction: 메시지 처리 및 데이터 저장.
  • Control: 메시지 전송 및 UI 업데이트 간의 흐름 제어.

2. 스마트 홈 시스템

  • Presentation: 사용자 입력을 받아 온도, 조명 등 설정.
  • Abstraction: 센서 데이터 처리 및 장치 상태 관리.
  • Control: 사용자 입력과 장치 간의 통신 흐름 제어.

3. 도서 관리 시스템

  • Presentation: 도서 목록 출력 및 사용자 입력 처리.
  • Abstraction: 도서 데이터베이스 관리.
  • Control: 사용자 요청에 따라 도서 추가, 삭제, 검색 흐름 제어.

C++ 예제 코드: 간단한 도서 관리 시스템

#include <iostream>
#include <vector>
#include <string>
#include <algorithm> // find 함수 사용을 위해 필요
#include <limits> // numeric_limits 사용을 위해 필요
#include <stdexcept> // runtime_error 사용을 위해 필요
using namespace std;

// Abstraction: 도서 데이터 처리 및 비즈니스 로직
class BookAbstraction {
private:
    vector<string> books;

public:
    void addBook(const string& book) {
        books.push_back(book);
    }

    void removeBook(const string& book) {
        auto it = find(books.begin(), books.end(), book);
        if (it != books.end()) {
            books.erase(it);
        } else {
            throw runtime_error("Book not found.");
        }
    }

    vector<string> getBooks() const {
        return books;
    }
};

// Control: 흐름 제어
class BookControl {
private:
    BookAbstraction& abstraction;

public:
    BookControl(BookAbstraction& abstraction) : abstraction(abstraction) {}

    void addBook(const string& book) {
        abstraction.addBook(book);
    }

    void removeBook(const string& book) {
        abstraction.removeBook(book);
    }

    vector<string> getBooks() const {
        return abstraction.getBooks();
    }
};

// Presentation: 사용자 인터페이스
class BookPresentation {
private:
    void clearScreen() {
#ifdef _WIN32
        system("cls");
#else
        system("clear");
#endif
    }

    BookControl& control;

public:
    BookPresentation(BookControl& control) : control(control) {}

    void showMenu() {
        while (true) {
            clearScreen();
            cout << "1. Add Book" << endl;
            cout << "2. Remove Book" << endl;
            cout << "3. View Books" << endl;
            cout << "4. Exit" << endl;
            cout << "Choose an option: ";

            int choice;
            if (!(cin >> choice)) {
                cin.clear();
                cin.ignore(numeric_limits<streamsize>::max(), '\n');
                cout << "Invalid input. Please enter a number." << endl;
                continue;
            }

            cin.ignore(numeric_limits<streamsize>::max(), '\n');

            if (choice == 1) {
                cout << "Enter book title: ";
                string book;
                getline(cin, book);
                control.addBook(book);
                cout << "Book added successfully!" << endl;
            } else if (choice == 2) {
                cout << "Enter book title to remove: ";
                string book;
                getline(cin, book);
                try {
                    control.removeBook(book);
                    cout << "Book removed successfully!" << endl;
                } catch (const runtime_error& e) {
                    cout << e.what() << endl;
                }
            } else if (choice == 3) {
                vector<string> books = control.getBooks();
                if (books.empty()) {
                    cout << "No books available." << endl;
                } else {
                    cout << "Books:" << endl;
                    for (const auto& book : books) {
                        cout << "- " << book << endl;
                    }
                }
            } else if (choice == 4) {
                break;
            } else {
                cout << "Invalid choice. Try again." << endl;
            }
        }
    }
};

// Main: 애플리케이션 실행
int main() {
    BookAbstraction abstraction;
    BookControl control(abstraction);
    BookPresentation presentation(control);

    presentation.showMenu();

    return 0;
}

코드 설명

Abstraction

  • BookAbstraction: 도서 데이터를 저장, 추가, 삭제.

Control

  • BookControl: Presentation과 Abstraction 간의 흐름을 제어.

Presentation

  • BookPresentation: 사용자 입력 처리 및 UI 출력.

실행 결과 예시

1. Add Book
2. Remove Book
3. View Books
4. Exit
Choose an option: 1
Enter book title: The Great Gatsby
Book added successfully!

1. Add Book
2. Remove Book
3. View Books
4. Exit
Choose an option: 3
Books:
- The Great Gatsby

1. Add Book
2. Remove Book
3. View Books
4. Exit
Choose an option: 4

PAC 패턴 요약

  1. Presentation: 사용자와 상호작용하며 UI를 처리.
  2. Abstraction: 데이터와 비즈니스 로직을 처리.
  3. Control: Presentation과 Abstraction 간의 흐름을 제어.

PAC 패턴은 복잡한 시스템을 계층적으로 설계해야 할 때 유용하며, 높은 모듈화와 확장성을 제공합니다.