Factory dan Abstract Factory
Termasuk bagian Pemrograman Berorientasi Object dalam perjalanan C++ di Coddy. Pelajaran 92 dari 104.
Factory pattern mendelegasikan pembuatan object ke method atau class terpisah, sehingga kamu dapat membuat object tanpa menentukan class spesifiknya. Pola ini berguna saat logika pembuatannya kompleks atau saat kamu ingin memisahkan kode client dari implementasi konkret.
Factory sederhana menggunakan method yang mengembalikan berbagai tipe turunan berdasarkan input:
#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"; }
};
// Fungsi factory
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;
}Abstract Factory melangkah lebih jauh dengan membuat kelompok object yang saling berkaitan. Alih-alih satu method factory, kamu memiliki antarmuka factory dengan beberapa method untuk membuat object:
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"; }
};
// Abstract Factory
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>();
}
};Gunakan Factory saat kamu membutuhkan pembuatan object yang fleksibel, dan Abstract Factory saat kamu perlu memastikan bahwa object yang saling terkait bekerja bersama secara konsisten.
Tantangan
MudahMari kita buat sistem Document Generator menggunakan pola Factory dan Abstract Factory. Kamu akan membuat sistem yang dapat menghasilkan berbagai jenis dokumen (laporan dan faktur) dalam berbagai format output (PDF dan HTML), untuk menunjukkan bagaimana factory memisahkan pembuatan object dari kode client.
Kamu akan mengatur kodemu dalam empat file:
Document.h: Definisikan hierarki produk dokumenmu.Buat class dasar abstrak
Documentdengan method virtual murnigenerate()yang mengembalikan string berisi deskripsi dokumen yang dihasilkan, serta destructor virtual.Lalu buat empat class dokumen konkret:
PDFReport:generate()mengembalikan"Generating PDF Report"HTMLReport:generate()mengembalikan"Generating HTML Report"PDFInvoice:generate()mengembalikan"Generating PDF Invoice"HTMLInvoice:generate()mengembalikan"Generating HTML Invoice"
DocumentFactory.h: Implementasikan fungsi factory sederhana dan abstract factory.Pertama, buat fungsi factory sederhana bernama
createDocumentyang menerima dua string: jenis dokumen ("report"atau"invoice") dan format ("pdf"atau"html"). Fungsi ini harus mengembalikanstd::unique_ptr<Document>yang menunjuk ke dokumen konkret yang sesuai. Kembalikannullptruntuk kombinasi yang tidak valid.Lalu buat class abstract factory bernama
DocumentFactorydengan dua method virtual murni:createReport(): mengembalikanstd::unique_ptr<Document>createInvoice(): mengembalikanstd::unique_ptr<Document>
Implementasikan dua factory konkret:
PDFFactory: membuatPDFReportdanPDFInvoiceHTMLFactory: membuatHTMLReportdanHTMLInvoice
DocumentService.h: Buat service yang menggunakan abstract factory.Definisikan class
DocumentServiceyang menerimastd::unique_ptr<DocumentFactory>di constructornya. Class ini harus memiliki method bernamagenerateAllDocuments()yang menggunakan factory untuk membuat laporan dan faktur, lalu mencetak hasil pemanggilangenerate()pada masing-masing dokumen, satu per baris.main.cpp: Tunjukkan kedua pendekatan factory.Baca dua input:
- Jenis dokumen (
reportatauinvoice) - Format (
pdfatauhtml)
Pertama, gunakan fungsi factory sederhana untuk membuat dokumen berdasarkan input. Cetak hasil pemanggilan
generate()pada dokumen tersebut.Lalu cetak satu baris kosong.
Selanjutnya, buat
DocumentServicedengan factory yang sesuai berdasarkan input format (gunakanPDFFactoryuntukpdf,HTMLFactoryuntukhtml). PanggilgenerateAllDocuments()untuk menunjukkan bagaimana abstract factory membuat kumpulan dokumen yang saling terkait.- Jenis dokumen (
Contohnya, dengan input report dan pdf:
Generating PDF Report
Generating PDF Report
Generating PDF InvoiceDengan input invoice dan html:
Generating HTML Invoice
Generating HTML Report
Generating HTML InvoicePerhatikan bagaimana factory sederhana membuat satu dokumen berdasarkan kedua parameter, sedangkan abstract factory memastikan bahwa semua dokumen yang dibuat oleh sebuah service memiliki format yang sama. Inilah manfaat utama Abstract Factory saat kamu membutuhkan kumpulan object terkait yang bekerja bersama secara konsisten.
Coba sendiri
#include <iostream>
#include <string>
#include <memory>
#include "Document.h"
#include "DocumentFactory.h"
#include "DocumentService.h"
using namespace std;
int main() {
// Baca input
string documentType;
string format;
cin >> documentType;
cin >> format;
// TODO: Gunakan fungsi simple factory untuk membuat dokumen
// berdasarkan input documentType dan format
// Cetak hasil pemanggilan generate() pada dokumen tersebut
// Cetak baris kosong
cout << endl;
// TODO: Buat DocumentService dengan factory yang sesuai
// berdasarkan input format (PDFFactory untuk "pdf", HTMLFactory untuk "html")
// Panggil generateAllDocuments() untuk menunjukkan cara kerja abstract factory
return 0;
}
Pelajaran ini berisi kuis singkat. Mulai pelajarannya untuk menjawab kuis dan melacak progresmu.
Semua pelajaran di Pemrograman Berorientasi Object
1Dasar-Dasar OOP
File EksternalBuild dan Kompilasi C++File Header dan File SourceNamespace dan CakupanPengantar OOP dalam C++class vs objectPointer 'this'method (Fungsi Anggota)Atribut (Anggota Data)Dasar Ctor dan DtorRingkasan: Kalkulator Sederhana4Properti class
Anggota instance vs staticGetter dan setterFungsi anggota constKata kunci mutableMethod dan variabel staticFungsi dan class friendRangkuman, Pengelola Rekening Bank7Pewarisan
Pewarisan DasarTingkat Akses pada PewarisanUrutan Pemanggilan Ctor & DtorPenimpaan methodFungsi Virtual & VTablePewarisan BergandaPewarisan VirtualRangkuman: Hierarki Karyawan10Gambaran Umum STL
Gambaran Umum dan Filosofi STLKontainer STLIteratorAlgoritma STLFunctor dan Ekspresi LambdaRangkuman: Frekuensi Kata13Pola Desain Bagian 1
Pengantar Pola DesainPola SingletonFactory dan Abstract FactoryPola BuilderPola ObserverPola Strategy2Manajemen Memori
Memori Stack vs HeapPointer dan ReferenceMemori Dinamis (new/delete)Smart Pointer di C++RAII di C++Rangkuman: Pengelola Array Dinamis5Enkapsulasi
Penentu Akses dalam C++Penentu Akses secara MendalamPenyembunyian Informasistruct vs classNested dan Inner classRangkuman, Sistem Catatan Siswa8Polimorfisme
Polimorfisme saat Compile vs RuntimeOverloading FungsiMeninjau Kembali Fungsi VirtualFungsi Virtual MurniKelas AbstrakDesain Interface di C++Casting Dinamis & RTTIRangkuman: Kalkulator Bentuk3Konstruktor & Destruktor
Konstruktor DefaultKonstruktor BerparameterKonstruktor SalinKonstruktor PindahDaftar Inisialisasi KonstruktorKonstruktor DelegasiKupas Tuntas DestruktorAturan Tiga, Lima, dan NolRangkuman: class String6Overloading Operator
Pengantar Overloading OperatorOverloading Operator AritmetikaOverloading Operator PerbandinganOperator StreamOverloading Operator PenugasanOverloading Operator [] dan ()Operator Konversi TipeRingkasan, class Matrix9Template
Template FungsiTemplate classSpesialisasi TemplateTemplate VariadikDasar SFINAE & Type TraitsRangkuman, Container GenerikLatihan sendiri: Compiler C++ online