Menu
Coddy logo textTech

Kompozit Kalıbı

Coddy'nin C++ Journey'sinin Nesne Yönelimli Programlama bölümünün bir parçası. Ders 101 / 104.

Composite deseni, tek tek nesnelere ve nesne gruplarına aynı şekilde davranmanızı sağlar. Nesneleri, hem tek öğelerin hem de öğe kapsayıcılarının aynı arayüzü paylaştığı ağaç yapıları hâlinde birleştirir. Bu, dosya sistemleri, organizasyon şemaları veya kullanıcı arayüzü bileşenleri gibi hiyerarşileri temsil etmek için idealdir.

Örüntünün üç temel bölümü vardır: ortak işlemleri tanımlayan bir Component arayüzü, tek tek nesneleri temsil eden Leaf sınıfları ve alt öğeleri içeren ve işlemleri onlara devreden Composite sınıfları:

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

// Bileşen arayüzü
class FileSystemItem {
public:
    virtual void display(int indent = 0) const = 0;
    virtual int getSize() const = 0;
    virtual ~FileSystemItem() = default;
};

// Yaprak - bireysel dosyaları temsil eder
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; }
};

// Bileşik - diğer bileşenleri içerir
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;
    }
};

Folder bileşiği, alt öğeleri depolar ve bunlar üzerinde yineleme yaparak işlemleri gerçekleştirir. Bir klasör üzerinde getSize() çağırdığınızda, içerdiği tüm öğelerin toplam boyutunu özyinelemeli olarak hesaplar. İstemci kodunun bir dosyayla mı yoksa bir klasörle mi çalıştığını bilmesine gerek yoktur; her ikisi de aynı arayüze yanıt verir.

Parça-bütün hiyerarşilerini temsil etmeniz gerektiğinde ve istemcilerin tek tek nesnelerle bileşimleri aynı şekilde işlemesini istediğinizde Composite kullanın.

challenge icon

Görev

Kolay

Composite desenini kullanarak bir Organizasyon Şeması sistemi oluşturalım. Hem bireysel çalışanların hem de diğer çalışanları veya alt departmanları içeren departmanların aynı şekilde ele alınabileceği bir hiyerarşi oluşturacaksınız. Bu, gerçek şirketlerin nasıl yapılandırıldığını yansıtır: departmanlar insanları ve diğer departmanları içererek bir ağaç yapısı oluşturur.

Kodunuzu üç dosyaya düzenleyeceksiniz:

  • OrgComponent.h: Hem çalışanların hem de departmanların uygulayacağı bileşen arayüzünü tanımlayın.

    Aşağıdakilere sahip soyut bir OrgComponent sınıfı oluşturun:

    • getName(): bileşenin adını döndürür
    • getSalary(): toplam maaşı döndürür (çalışanlar için kendi maaşları; departmanlar için içerilen tüm maaşların toplamı)
    • display(int indent = 0): bileşeni uygun girintilemeyle görüntüler

    Sanal bir yıkıcı ekleyin.

  • Organization.h: yaprak ve bileşik sınıfları uygulayın.

    Bir ad ve maaş saklayan bir Employee sınıfı (yaprak) oluşturun. display() metodu, çalışanın bilgilerini şu biçimde yazdırmalıdır:

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

    Department kullanarak bir ad ve OrgComponent alt öğelerinden oluşan bir koleksiyon saklayan bir std::shared_ptr sınıfı (bileşik) oluşturun. Şunları uygulayın:

    • add(std::shared_ptr<OrgComponent> component): departmana bir alt öğe ekler
    • getSalary(): tüm üyelerin toplam maaşını özyinelemeli olarak hesaplar
    • display(): departman adını köşeli parantezler içinde yazdırır, ardından tüm alt öğeleri artırılmış girintiyle görüntüler (seviye başına 2 boşluk ekleyin)

    Departmanın görüntüleme biçimi şu şekilde olmalıdır:

    [indent spaces][Department Name]
      [children displayed with indent + 2]
  • main.cpp: bir organizasyon yapısı oluşturun ve görüntüleyin.

    Dört girdi okuyun:

    1. Şirket adı (string)
    2. Departman adı (string)
    3. İlk çalışanın adı ve maaşı (biçim: name,salary)
    4. İkinci çalışanın adı ve maaşı (biçim: name,salary)

    Bu yapıyı oluşturun: Bir şirket (en üst düzey departman) oluşturun, buna bir alt departman ekleyin ve her iki çalışanı da bu alt departmana ekleyin. Ardından tüm organizasyonu görüntüleyin ve toplam şirket maaşını yazdırın.

    Yapıyı görüntüledikten sonra şunu yazdırın:

    Total Salary: $[amount]

Örneğin TechCorp, Engineering, Alice,75000 ve Bob,65000 girdileriyle:

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

StartupInc, Development, Carol,80000 ve Dave,70000 girdileriyle:

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

getSalary() metodunun bir çalışan veya departman üzerinde çağrılmasına bakılmaksızın nasıl aynı şekilde çalıştığına dikkat edin: departman, tüm üyelerinin maaşlarını otomatik olarak toplar. Toplamları hesaplarken veya hiyerarşiyi görüntülerken istemci kodunun bireysel çalışanlar ile tüm departmanlar arasında ayrım yapmasına gerek yoktur.

Kendin dene

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

int main() {
    // Girdileri oku
    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);
    
    // "name,salary" formatını ayrıştırmak için yardımcı lambda
    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: Şirketi üst düzey bir Department olarak oluştur
    
    // TODO: Bir alt departman oluştur
    
    // TODO: Ayrıştırılmış verileri kullanarak iki Employee nesnesi oluştur
    
    // TODO: Çalışanları alt departmana ekle
    
    // TODO: Alt departmanı şirkete ekle
    
    // TODO: Tüm organizasyon yapısını görüntüle
    
    // TODO: Toplam maaşı şu formatta yazdır: Total Salary: $[amount]
    
    return 0;
}
quiz iconKendini test et

Bu ders kısa bir quiz içerir. Soruları yanıtlamak ve ilerlemeni kaydetmek için derse başla.

Nesne Yönelimli Programlama bölümündeki tüm dersler

Kendi başına pratik yap: Online C++ derleyicisi