Şablon Metot Kalıbı
Coddy'nin C++ Journey'sinin Nesne Yönelimli Programlama bölümünün bir parçası — ders 99 / 104.
Template Method deseni, bir algoritmanın iskeletini bir temel sınıfta tanımlar ve alt sınıfların, algoritmanın genel yapısını değiştirmeden belirli adımları geçersiz kılmasına (override) olanak tanır. Tüm algoritmaları yer değiştiren Strategy'nin aksine, Template Method algoritmayı sabit tutarken bireysel adımların özelleştirilmesine izin verir.
Temel sınıf, şablon yöntemini (algoritmayı) uygular ve alt sınıfların sağlaması gereken soyut veya sanal yöntemleri çağırır:
#include <iostream>
class DataProcessor {
public:
// Şablon metodu - algoritma iskeletini tanımlar
void process() {
loadData();
processData();
saveResults();
}
virtual ~DataProcessor() = default;
protected:
virtual void loadData() = 0; // Uygulanması zorunludur
virtual void processData() = 0; // Uygulanması zorunludur
// Hook (Kanca) - varsayılan davranışla isteğe bağlı geçersiz kılma
virtual void saveResults() {
std::cout << "Saving to default location\n";
}
};
class CSVProcessor : public DataProcessor {
protected:
void loadData() override {
std::cout << "Loading CSV file\n";
}
void processData() override {
std::cout << "Parsing CSV data\n";
}
};
class JSONProcessor : public DataProcessor {
protected:
void loadData() override {
std::cout << "Loading JSON file\n";
}
void processData() override {
std::cout << "Parsing JSON data\n";
}
void saveResults() override {
std::cout << "Saving to cloud storage\n";
}
};
int main() {
CSVProcessor csv;
csv.process(); // Varsayılan saveResults'ı kullanır
JSONProcessor json;
json.process(); // Özel saveResults'ı kullanır
}process() yöntemi şablon yöntemdir (template method); adımların sabit sırasını tanımlar. Alt sınıflar loadData() ve processData() yöntemlerini farklı şekilde uygular, ancak sıra asla değişmez. saveResults() yöntemi bir "hook"tur (kanca); alt sınıfların isteğe bağlı olarak geçersiz kılabileceği varsayılan bir uygulamaya sahiptir.
Değişmez adımlara sahip bir algoritmanız olduğunda ancak belirli işlemlerde esnekliğe ihtiyaç duyduğunuzda veya benzer sınıflar arasında kod tekrarından kaçınmak istediğinizde Template Method'u kullanın.
Görev
KolayTemplate Method desenini kullanarak bir Rapor Oluşturucu (Report Generator) sistemi inşa edelim. Farklı rapor türlerinin (satış raporları ve envanter raporları gibi) aynı oluşturma sürecini takip ettiği, ancak her rapor türünün belirli adımları özelleştirdiği bir iskelet oluşturacaksınız. Bu, Template Method için mükemmel bir senaryodur; genel iş akışı sabit kalırken bireysel adımlar değişir.
Kodunuzu üç dosya halinde düzenleyeceksiniz:
ReportGenerator.h: Şablon metodunu içeren soyut temel sınıfı tanımlayın.Rapor oluşturma algoritmasının iskeletini tanımlayan bir
ReportGeneratorsınıfı oluşturun. Şablon metodunuz olangenerateReport(), şu adımları sırasıyla yürütmelidir:gatherData()— saf sanal (pure virtual), alt sınıflar tarafından uygulanmalıdırformatReport()— saf sanal, alt sınıflar tarafından uygulanmalıdıraddHeader()— varsayılan davranışı--- Report ---yazdıran bir kanca (hook)printReport()— saf sanal, alt sınıflar tarafından uygulanmalıdır
addHeader()metodu, alt sınıfların başlığı özelleştirmek için isteğe bağlı olarak geçersiz kılabileceği (override) bir kanca görevi görür.Reports.h: İki somut rapor oluşturucuyu uygulayın.Şu özelliklere sahip bir
SalesReportsınıfı oluşturun:gatherData()şunu yazdırır:Gathering sales data from databaseformatReport()şunu yazdırır:Formatting sales figuresprintReport()şunu yazdırır:Sales Total: $[amount](burada amount yapıcıya (constructor) iletilen değerdir)
Şu özelliklere sahip bir
InventoryReportsınıfı oluşturun:gatherData()şunu yazdırır:Scanning inventory recordsformatReport()şunu yazdırır:Organizing inventory by categoryaddHeader()kancayı geçersiz kılarak şunu yazdırır:=== Inventory Report ===printReport()şunu yazdırır:Items in stock: [count](burada count yapıcıya iletilen değerdir)
Her iki sınıf da ilgili değerlerini (amount veya count) yapıcıları aracılığıyla kabul etmelidir.
main.cpp: Template Method desenini gösterin.İki girdi okuyun:
- Satış tutarı (tam sayı)
- Envanter sayısı (tam sayı)
Satış tutarı ile bir
SalesReportoluşturun ve raporu üretin. Ardından envanter sayısı ile birInventoryReportoluşturun ve raporu üretin. Okunabilirlik için iki rapor arasına boş bir satır yazdırın.
Örneğin, 15000 ve 250 girdileriyle:
Gathering sales data from database
Formatting sales figures
--- Report ---
Sales Total: $15000
Scanning inventory records
Organizing inventory by category
=== Inventory Report ===
Items in stock: 2508500 ve 120 girdileriyle:
Gathering sales data from database
Formatting sales figures
--- Report ---
Sales Total: $8500
Scanning inventory records
Organizing inventory by category
=== Inventory Report ===
Items in stock: 120Her iki raporun da generateReport() içinde tanımlanan tam olarak aynı adımlar dizisini nasıl takip ettiğine, ancak her birinin bu adımları nasıl farklı şekilde uyguladığına dikkat edin. InventoryReport ayrıca başlığı özelleştirmek için kanca metodunu geçersiz kılmayı gösterirken, SalesReport varsayılanı kullanır. Bu, Template Method deseninin iş başındaki halidir; algoritma yapısı temel sınıfta kilitlenmiştir, ancak ayrıntılar esnektir.
Kopya kağıdı
Template Method deseni, bir algoritmanın iskeletini bir temel sınıfta tanımlar ve alt sınıfların, algoritmanın genel yapısını değiştirmeden belirli adımları geçersiz kılmasına (override) olanak tanır.
Temel sınıf, şablon yöntemi (algoritmayı) uygular ve alt sınıfların sağlaması gereken soyut veya sanal yöntemleri çağırır:
#include <iostream>
class DataProcessor {
public:
// Şablon yöntemi - algoritma iskeletini tanımlar
void process() {
loadData();
processData();
saveResults();
}
virtual ~DataProcessor() = default;
protected:
virtual void loadData() = 0; // Uygulanması zorunludur
virtual void processData() = 0; // Uygulanması zorunludur
// Hook - varsayılan davranışla isteğe bağlı geçersiz kılma
virtual void saveResults() {
std::cout << "Saving to default location\n";
}
};
class CSVProcessor : public DataProcessor {
protected:
void loadData() override {
std::cout << "Loading CSV file\n";
}
void processData() override {
std::cout << "Parsing CSV data\n";
}
};
class JSONProcessor : public DataProcessor {
protected:
void loadData() override {
std::cout << "Loading JSON file\n";
}
void processData() override {
std::cout << "Parsing JSON data\n";
}
void saveResults() override {
std::cout << "Saving to cloud storage\n";
}
};Şablon yöntemi, sabit bir adım dizisini tanımlar. Alt sınıflar soyut yöntemleri farklı şekilde uygular, ancak sıra asla değişmez. Hook yöntemleri, alt sınıfların isteğe bağlı olarak geçersiz kılabileceği varsayılan uygulamalara sahiptir.
Değişmez adımları olan bir algoritmanız olduğunda ancak belirli işlemlerde esnekliğe ihtiyaç duyduğunuzda veya benzer sınıflar arasında kod tekrarını önlemek istediğinizde Template Method kullanın.
Kendin dene
#include <iostream>
#include "Reports.h"
using namespace std;
int main() {
// Girdileri oku
int salesAmount;
int inventoryCount;
cin >> salesAmount;
cin >> inventoryCount;
// TODO: salesAmount ile bir SalesReport oluşturun ve bunu oluşturun (generate)
// TODO: Raporlar arasına boş bir satır yazdırın
// TODO: inventoryCount ile bir InventoryReport oluşturun ve bunu oluşturun (generate)
return 0;
}
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
1OOP Temelleri
Harici DosyalarC++ Build ve DerlemeBaşlık Dosyaları ve Kaynak DosyalarıAd Alanları ve KapsamC++'ta OOP'ye GirişSınıflar ve Nesneler'this' İşaretçisiMetotlar (Üye Fonksiyonlar)Öznitelikler (Veri Üyeleri)Ctor ve Dtor TemelleriÖzet - Basit Hesap Makinesi4Sınıf Özellikleri
Örnek ve Statik ÜyelerGetter ve Setter MetotlarıConst Üye FonksiyonlarMutable Anahtar KelimesiStatik Metotlar ve DeğişkenlerFriend Fonksiyonlar ve SınıflarÖzet - Banka Hesabı Yöneticisi7Kalıtım
Temel KalıtımKalıtım Erişim SeviyeleriCtor ve Dtor Çağrılma SırasıMetot Geçersiz KılmaSanal Fonksiyonlar ve VTableÇoklu KalıtımSanal KalıtımÖzet - Çalışan Hiyerarşisi10STL Genel Bakış
STL Genel Bakış ve FelsefesiSTL KonteynerleriİteratörlerSTL AlgoritmalarıFunctor'lar ve Lambda İfadeleriÖzet - Kelime Frekansı13Tasarım Kalıpları 1. Bölüm
Tasarım Kalıplarına GirişSingleton KalıbıFactory ve Abstract FactoryBuilder KalıbıObserver KalıbıStrategy Kalıbı2Bellek Yönetimi
Stack ve Heap Bellekİşaretçiler ve ReferanslarDinamik Bellek (new/delete)C++'ta Akıllı İşaretçilerC++'ta RAIIÖzet - Dinamik Dizi Yöneticisi5Kapsülleme
C++'da Erişim BelirleyicilerDerinlemesine Erişim BelirleyicilerBilgi GizlemeStruct vs Classİç İçe ve Dahili SınıflarÖzet - Öğrenci Kayıt Sistemi8Çok Biçimlilik
Derleme ve Çalışma Zamanı Çok BiçimliliğiFonksiyon Aşırı YüklemeSanal Fonksiyonlara Yeniden BakışSaf Sanal FonksiyonlarSoyut SınıflarC++'ta Arayüz TasarımıDynamic Casting ve RTTIÖzet - Şekil Hesaplayıcı11İleri Düzey OOP Kavramları
Kompozisyon ve Kalıtım KarşılaştırmasıCRTP ile Mixin YapılarıPimpl İdiyomuTür Silme (Type Erasure)Enum Sınıfları ve Güçlü TiplendirmeOOP'de İstisna YönetimiÖzel İstisna Hiyerarşileri14Tasarım Kalıpları Bölüm 2
Komut KalıbıAdaptör KalıbıDekoratör KalıbıŞablon Metot KalıbıDurum KalıbıKompozit KalıbıBir Kalıp Olarak RAII3Yapıcılar ve Yıkıcılar
Varsayılan YapıcıParametreli YapıcıKopya YapıcıTaşıma YapıcısıYapıcı İlklendirme ListeleriTemsilci YapıcılarYıkıcılara Derinlemesine BakışÜç / Beş / Sıfır KuralıÖzet - String Sınıfı6Operatör Aşırı Yükleme
Operatör Aşırı Yüklemeye GirişAritmetik Operatör Aşırı YüklemeKarşılaştırma Operatörü Aşırı YüklemeStream OperatörleriAtama Operatörü Aşırı Yükleme[] ve () Operatör Aşırı YüklemeTip Dönüşüm OperatörleriÖzet - Matris Sınıfı9Şablonlar
Fonksiyon ŞablonlarıSınıf ŞablonlarıŞablon ÖzelleştirmeVariadic ŞablonlarSFINAE ve Type Traits TemelleriÖzet - Generic Konteyner