Design patterns
- C++ kursu
- İleri seviye
- Ders 82/83
- 6 dk
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
#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
#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
static Logger& ____() { static Logger inst; return inst; }
static Logger& instance() { static Logger inst; return inst; }
Açıklama: instance() singleton'un tek örneğini döndürür.