Menu
CoddyTech

Pola Composite

Termasuk bagian Pemrograman Berorientasi Object dalam perjalanan C++ di Coddy. Pelajaran 101 dari 104.

Pola Composite memungkinkan kamu memperlakukan object individual dan kelompok object secara seragam. Pola ini menyusun object menjadi struktur pohon, tempat elemen tunggal dan container elemen menggunakan antarmuka yang sama. Pola ini ideal untuk merepresentasikan hierarki seperti sistem file, bagan organisasi, atau komponen UI.

Pola ini memiliki tiga bagian utama: antarmuka Component yang mendefinisikan operasi umum, class Leaf yang merepresentasikan object individual, dan class Composite yang berisi anak dan mendelegasikan operasi kepada mereka:

#include <iostream>
#include <memory>
#include <vector>
#include <string>

// Antarmuka komponen
class FileSystemItem {
public:
    virtual void display(int indent = 0) const = 0;
    virtual int getSize() const = 0;
    virtual ~FileSystemItem() = default;
};

// Daun: mewakili file individual
class File : public FileSystemItem {
    std::string name;
    int size;
public:
    File(const std::string& n, int s) : name(n), size(s) {}
    
    void display(int indent = 0) const override {
        std::cout << std::string(indent, ' ') << name 
                  << " (" << size << " KB)\n";
    }
    int getSize() const override { return size; }
};

// Komposit: berisi komponen lain
class Folder : public FileSystemItem {
    std::string name;
    std::vector<std::shared_ptr<FileSystemItem>> children;
public:
    Folder(const std::string& n) : name(n) {}
    
    void add(std::shared_ptr<FileSystemItem> item) {
        children.push_back(item);
    }
    
    void display(int indent = 0) const override {
        std::cout << std::string(indent, ' ') << "[" << name << "]\n";
        for (const auto& child : children) {
            child->display(indent + 2);
        }
    }
    
    int getSize() const override {
        int total = 0;
        for (const auto& child : children) {
            total += child->getSize();
        }
        return total;
    }
};

Composite Folder menyimpan child dan mengimplementasikan operasi dengan melakukan iterasi pada child tersebut. Saat kamu memanggil getSize() pada folder, composite tersebut menghitung total ukuran semua item di dalamnya secara rekursif. Kode client tidak perlu mengetahui apakah kode tersebut bekerja dengan file atau folder, keduanya merespons dengan interface yang sama.

Gunakan Composite saat kamu perlu merepresentasikan hierarki bagian-keseluruhan dan ingin client memperlakukan object individual dan komposisi secara seragam.

challenge icon

Tantangan

Mudah

Mari kita buat sistem Bagan Organisasi menggunakan pola Composite. Kamu akan membuat hierarki tempat karyawan perorangan dan departemen, yang berisi karyawan lain atau subdepartemen, dapat diperlakukan secara seragam. Ini mencerminkan struktur perusahaan di dunia nyata: departemen berisi orang dan departemen lain, sehingga membentuk struktur pohon.

Kamu akan mengatur kodemu dalam tiga file:

  • OrgComponent.h: Definisikan antarmuka komponen yang akan diterapkan oleh karyawan dan departemen.

    Buat class abstrak OrgComponent dengan:

    • getName(): mengembalikan nama komponen
    • getSalary(): mengembalikan total gaji. Untuk karyawan, gaji mereka sendiri. Untuk departemen, jumlah semua gaji yang tercakup di dalamnya.
    • display(int indent = 0): menampilkan komponen dengan indentasi yang sesuai

    Sertakan destructor virtual.

  • Organization.h: Implementasikan class leaf dan composite.

    Buat class Employee (leaf) yang menyimpan nama dan gaji. Method display()-nya harus mencetak informasi karyawan dengan format berikut:

    [indent spaces]- [name] ($[salary])

    Buat class Department (composite) yang menyimpan nama dan kumpulan anak OrgComponent menggunakan std::shared_ptr. Implementasikan:

    • add(std::shared_ptr<OrgComponent> component): menambahkan anak ke departemen
    • getSalary(): menghitung total gaji semua anggota secara rekursif
    • display(): mencetak nama departemen di dalam tanda kurung siku, lalu menampilkan semua anak dengan indentasi yang bertambah sebanyak 2 spasi per tingkat

    Format tampilan departemen harus seperti berikut:

    [indent spaces][Department Name]
      [children displayed with indent + 2]
  • main.cpp: Buat dan tampilkan struktur organisasi.

    Baca empat input:

    1. Nama perusahaan (string)
    2. Nama departemen (string)
    3. Nama dan gaji karyawan pertama (format: name,salary)
    4. Nama dan gaji karyawan kedua (format: name,salary)

    Buat struktur ini: Buat perusahaan (departemen tingkat teratas), tambahkan subdepartemen ke dalamnya, lalu tambahkan kedua karyawan ke subdepartemen tersebut. Setelah itu, tampilkan seluruh organisasi dan cetak total gaji perusahaan.

    Setelah menampilkan struktur, cetak:

    Total Salary: $[amount]

Contohnya, dengan input TechCorp, Engineering, Alice,75000, dan Bob,65000:

[TechCorp]
  [Engineering]
    - Alice ($75000)
    - Bob ($65000)
Total Salary: $140000

Dengan input StartupInc, Development, Carol,80000, dan Dave,70000:

[StartupInc]
  [Development]
    - Carol ($80000)
    - Dave ($70000)
Total Salary: $150000

Perhatikan bahwa getSalary() bekerja secara seragam, baik dipanggil pada karyawan maupun departemen: departemen secara otomatis mengakumulasi gaji semua anggotanya. Kode client tidak perlu membedakan karyawan perorangan dan seluruh departemen saat menghitung total atau menampilkan hierarki.

Coba sendiri

#include <iostream>
#include <string>
#include <memory>
#include <sstream>
#include "Organization.h"

int main() {
    // Baca input
    std::string companyName;
    std::string departmentName;
    std::string employee1Input;
    std::string employee2Input;
    
    std::getline(std::cin, companyName);
    std::getline(std::cin, departmentName);
    std::getline(std::cin, employee1Input);
    std::getline(std::cin, employee2Input);
    
    // Lambda pembantu untuk mengurai format "name,salary"
    auto parseEmployee = [](const std::string& input) -> std::pair<std::string, int> {
        size_t commaPos = input.find(',');
        std::string name = input.substr(0, commaPos);
        int salary = std::stoi(input.substr(commaPos + 1));
        return {name, salary};
    };
    
    auto [name1, salary1] = parseEmployee(employee1Input);
    auto [name2, salary2] = parseEmployee(employee2Input);
    
    // TODO: Buat perusahaan sebagai Department tingkat teratas
    
    // TODO: Buat subdepartemen
    
    // TODO: Buat dua object Employee menggunakan data yang telah diurai
    
    // TODO: Tambahkan kedua karyawan ke subdepartemen
    
    // TODO: Tambahkan subdepartemen ke perusahaan
    
    // TODO: Tampilkan seluruh struktur organisasi
    
    // TODO: Cetak total gaji dengan format: Total Salary: $[amount]
    
    return 0;
}
quiz iconUji dirimu

Pelajaran ini berisi kuis singkat. Mulai pelajarannya untuk menjawab kuis dan melacak progresmu.

Semua pelajaran di Pemrograman Berorientasi Object

Latihan sendiri: Compiler C++ online