CodeBlanks Logo Icon CodeBlanks

Design patterns

Tasarım desenleriyle modüler yapı yazarsın.

Design patterns katmanı

Bu derste projeye iki tasarım deseni ekleyeceğiz: Singleton (Logger) ve Factory (TaskFactory). Bu desenler kodu modüler ve genişletilebilir yapar.

Logger singleton: tek örnek, globale erişim. static Logger& instance() ile alınır. TaskFactory::makePrint, PrintTask üretir. PrintTask, soyut Task arayüzünden türetilir ve execute() metodu Logger'a yazar. Böylece yeni görev türleri eklemek kolaylaşır: yalnızca yeni bir Task türevi ve factory metodu yazarsın. Önceki katmanlar yerinde kalır.

Task arayüzü ve Factory

Task soyut arayüzüdür: virtual void execute() = 0;. PrintTask bunu uygular. TaskFactory::makePrint, std::unique_ptr<Task> döndürür.

Örnek: auto t = TaskFactory::makePrint("görev tamam"); t->execute();. makePrint bir PrintTask üretir ama Task arayüzü üzerinden verir. Bu, çağıranın somut türü bilmeden görev çalıştırmasını sağlar. Yeni görev türü eklemek için yalnızca yeni bir Task türevi ve yeni bir factory metodu yazarsın. std::make_unique belleği güvenle yönetir.

Uygulama Logger ve TaskFactory ekle

Logger singleton sınıfını yaz: static Logger& instance() ve void log(const std::string& msg) üyeleri olsun. Task soyut arayüzünü, PrintTask türevini ve TaskFactory::makePrint factory metodunu ekle. run içinde auto t = TaskFactory::makePrint("görev tamam"); t->execute(); satırlarını ekle (önceki satırı << std::endl ile bitir).

Başlangıç kodu

main.cpp
#include <iostream>
#include <string>
#include <vector>
#include <ranges>
#include <algorithm>
#include <concepts>
#include <thread>
#include <atomic>
#include <memory>

// Logger sinifini yaz (singleton)
// Task arayuzu ve PrintTask yaz
// TaskFactory yaz (makePrint)

class Framework {
public:
    int run();
    template<std::integral T>
    int process_data(const std::vector<T>& data);
    int parallel_sum(const std::vector<int>& data);
};

template<std::integral T>
int Framework::process_data(const std::vector<T>& data) {
    int sum = 0;
    for (auto x : data | std::views::filter([](T v) { return v > 0; })) {
        sum += x;
    }
    return sum;
}

int Framework::parallel_sum(const std::vector<int>& data) {
    std::atomic<int> total{0};
    std::thread t1([&]() { for (auto x : data) if (x > 0) total += x; });
    t1.join();
    return total;
}

int Framework::run() {
    std::cout << "Proje hazır" << std::endl;
    std::vector<int> data{1, -2, 3};
    std::cout << "toplam: " << process_data(data) << std::endl;
    std::cout << "paralel: " << parallel_sum(data) << std::endl;
    // TaskFactory::makePrint ile görev oluştur ve execute et
    return 0;
}

int main() {
    Framework fw;
    fw.run();
    return 0;
}

Örnek çözüm

main.cpp
#include <iostream>
#include <string>
#include <vector>
#include <ranges>
#include <algorithm>
#include <concepts>
#include <thread>
#include <atomic>
#include <memory>

class Logger {
public:
    static Logger& instance() {
        static Logger inst;
        return inst;
    }
    void log(const std::string& msg) { std::cout << "[log] " << msg; }
private:
    Logger() = default;
};

class Task {
public:
    virtual ~Task() = default;
    virtual void execute() = 0;
};

class PrintTask : public Task {
public:
    PrintTask(const std::string& m) : msg_(m) {}
    void execute() override { Logger::instance().log(msg_); }
private:
    std::string msg_;
};

class TaskFactory {
public:
    static std::unique_ptr<Task> makePrint(const std::string& m) {
        return std::make_unique<PrintTask>(m);
    }
};

class Framework {
public:
    int run();
    template<std::integral T>
    int process_data(const std::vector<T>& data);
    int parallel_sum(const std::vector<int>& data);
};

template<std::integral T>
int Framework::process_data(const std::vector<T>& data) {
    int sum = 0;
    for (auto x : data | std::views::filter([](T v) { return v > 0; })) {
        sum += x;
    }
    return sum;
}

int Framework::parallel_sum(const std::vector<int>& data) {
    std::atomic<int> total{0};
    std::thread t1([&]() { for (auto x : data) if (x > 0) total += x; });
    t1.join();
    return total;
}

int Framework::run() {
    std::cout << "Proje hazır" << std::endl;
    std::vector<int> data{1, -2, 3};
    std::cout << "toplam: " << process_data(data) << std::endl;
    std::cout << "paralel: " << parallel_sum(data) << std::endl;
    auto t = TaskFactory::makePrint("görev tamam");
    t->execute();
    return 0;
}

int main() {
    Framework fw;
    fw.run();
    return 0;
}

Beklenen çıktı

Proje hazır
toplam: 4
paralel: 4
[log] görev tamam

Soru ve cevaplar

Dersin sorularını cevaplarıyla birlikte inceleyebilirsin. Kendini denemek istersen dersi interaktif olarak çöz.

1 Singleton deseni ne sağlar?

  • Birden çok örnek
  • Tek örnek ve globale erişim Doğru cevap
  • Çoklu iş parçacığı
  • Otomatik bellek temizliği

Açıklama: Singleton, tek örnek ve globale erişim sağlar.

2 Deseni açıklamasıyla eşle

Kavram Anlamı
Singleton Tek örnek
Factory Nesne üretimi
Logger Günlük tutucu
Task Soyut iş

3 static instance

Soru
static Logger& ____() { static Logger inst; return inst; }
Cevap
static Logger& instance() { static Logger inst; return inst; }

Açıklama: instance() singleton'un tek örneğini döndürür.

İleri seviye bölümündeki tüm dersler