Factory ve Abstract Factory
Coddy'nin C++ Journey'sinin Nesne Yönelimli Programlama bölümünün bir parçası. Ders 92 / 104.
Factory kalıbı, nesne oluşturma işlemini ayrı bir yönteme veya sınıfa devreder ve tam sınıfını belirtmeden nesneler oluşturmanıza olanak tanır. Bu, oluşturma mantığı karmaşık olduğunda veya istemci kodunu somut uygulamalardan ayırmak istediğinizde kullanışlıdır.
Basit bir fabrika, girdiye göre farklı türetilmiş türler döndüren bir yöntem kullanır:
#include <iostream>
#include <memory>
class Button {
public:
virtual void render() = 0;
virtual ~Button() = default;
};
class WindowsButton : public Button {
public:
void render() override { std::cout << "Windows button\n"; }
};
class MacButton : public Button {
public:
void render() override { std::cout << "Mac button\n"; }
};
// Fabrika fonksiyonu
std::unique_ptr<Button> createButton(const std::string& os) {
if (os == "windows") return std::make_unique<WindowsButton>();
if (os == "mac") return std::make_unique<MacButton>();
return nullptr;
}Soyut Fabrika bunu bir adım ileri taşıyarak birbiriyle ilişkili nesne aileleri oluşturur. Tek bir fabrika yöntemi yerine, birden çok oluşturma yöntemine sahip bir fabrika arayüzünüz olur:
class Checkbox {
public:
virtual void check() = 0;
virtual ~Checkbox() = default;
};
class WindowsCheckbox : public Checkbox {
public:
void check() override { std::cout << "Windows checkbox\n"; }
};
class MacCheckbox : public Checkbox {
public:
void check() override { std::cout << "Mac checkbox\n"; }
};
// Soyut Fabrika
class GUIFactory {
public:
virtual std::unique_ptr<Button> createButton() = 0;
virtual std::unique_ptr<Checkbox> createCheckbox() = 0;
virtual ~GUIFactory() = default;
};
class WindowsFactory : public GUIFactory {
public:
std::unique_ptr<Button> createButton() override {
return std::make_unique<WindowsButton>();
}
std::unique_ptr<Checkbox> createCheckbox() override {
return std::make_unique<WindowsCheckbox>();
}
};Esnek nesne oluşturma gerektiğinde Factory’yi, ilişkili nesnelerin tutarlı bir şekilde birlikte çalışmasını sağlamanız gerektiğinde ise Abstract Factory’yi kullanın.
Görev
KolayFactory ve Abstract Factory kalıplarını kullanarak bir Belge Oluşturucu sistemi oluşturalım. Farklı çıktı biçimleri (PDF ve HTML) için farklı belge türleri (raporlar ve faturalar) oluşturabilen bir sistem geliştirecek ve factory'lerin nesne oluşturmayı istemci kodundan nasıl ayırdığını göstereceksin.
Kodunu dört dosya arasında düzenleyeceksin:
Document.h: Belge ürün hiyerarşisini tanımla.Üretilen belgeyi açıklayan bir dize döndüren saf sanal
Documentmetoduna ve sanal bir yıkıcıya sahip soyut bir temelgenerate()sınıfı oluştur.Ardından dört somut belge sınıfı oluştur:
PDFReport:generate(),"Generating PDF Report"döndürürHTMLReport:generate(),"Generating HTML Report"döndürürPDFInvoice:generate(),"Generating PDF Invoice"döndürürHTMLInvoice:generate(),"Generating HTML Invoice"döndürür
DocumentFactory.h: Hem basit bir factory fonksiyonu hem de abstract factory uygula.İlk olarak, iki dize alan
createDocumentadlı basit bir factory fonksiyonu oluştur: bir belge türü ("report"veya"invoice") ve bir biçim ("pdf"veya"html"). Uygun somut belgeyi gösteren birstd::unique_ptr<Document>döndürmelidir. Geçersiz birleşimler içinnullptrdöndür.Ardından iki saf sanal metoda sahip
DocumentFactoryadlı bir abstract factory sınıfı oluştur:createReport(): birstd::unique_ptr<Document>döndürürcreateInvoice(): birstd::unique_ptr<Document>döndürür
İki somut factory uygula:
PDFFactory:PDFReportvePDFInvoiceoluştururHTMLFactory:HTMLReportveHTMLInvoiceoluşturur
DocumentService.h: Abstract factory kullanan bir servis oluştur.Yapıcısında
DocumentServicealan birstd::unique_ptr<DocumentFactory>sınıfı tanımla. Bu sınıf, factory'yi kullanarak hem bir rapor hem de bir fatura oluşturan, ardından her biri üzerindegenerateAllDocuments()çağrısının sonucunu satır başına bir tane olacak şekilde yazdırangenerate()adlı bir metoda sahip olmalıdır.main.cpp: Her iki factory yaklaşımını göster.İki girdi oku:
- Bir belge türü (
reportveyainvoice) - Bir biçim (
pdfveyahtml)
İlk olarak, girdilere göre bir belge oluşturmak için basit factory fonksiyonunu kullan. Üzerinde
generate()çağrısının sonucunu yazdır.Ardından boş bir satır yazdır.
Sonra biçim girdisine göre uygun factory ile bir
DocumentServiceoluştur (PDFFactoryiçinpdf,HTMLFactoryiçinhtmlkullan). Abstract factory'nin birbiriyle ilişkili belge ailesi oluşturma biçimini göstermek içingenerateAllDocuments()çağrısını yap.- Bir belge türü (
Örneğin, girdiler report ve pdf olduğunda:
Generating PDF Report
Generating PDF Report
Generating PDF InvoiceGirdiler invoice ve html olduğunda:
Generating HTML Invoice
Generating HTML Report
Generating HTML InvoiceBasit factory'nin her iki parametreye göre tek bir belge oluşturduğuna, abstract factory'nin ise bir servis tarafından oluşturulan tüm belgelerin aynı biçimi paylaşmasını sağladığına dikkat et. Bu, birlikte tutarlı biçimde çalışması gereken birbiriyle ilişkili nesne ailelerine ihtiyaç duyduğunda Abstract Factory'nin temel avantajıdır.
Kendin dene
#include <iostream>
#include <string>
#include <memory>
#include "Document.h"
#include "DocumentFactory.h"
#include "DocumentService.h"
using namespace std;
int main() {
// Girdileri oku
string documentType;
string format;
cin >> documentType;
cin >> format;
// TODO: Bir belge oluşturmak için basit fabrika fonksiyonunu kullan
// documentType ve format girdilerine göre
// Üzerinde generate() çağrısının sonucunu yazdır
// Boş bir satır yazdır
cout << endl;
// TODO: Uygun fabrika ile bir DocumentService oluştur
// format girdisine göre ("pdf" için PDFFactory, "html" için HTMLFactory)
// Soyut fabrikayı göstermek için generateAllDocuments() çağır
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ı3Yapı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 KonteynerKendi başına pratik yap: Online C++ derleyicisi