-
-
Notifications
You must be signed in to change notification settings - Fork 47
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch 'bellshade:main' into aj
- Loading branch information
Showing
12 changed files
with
436 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
# Design patterns | ||
|
||
Seiring waktu yang terus berjalan, software pun akan terus mengalami | ||
pengembangan, agar komunikasi antar *objects*, pembuatan *objects*, | ||
dan struktur atau relasi antar *classes* dalam aplikasi tersebut | ||
berjalan lancar, *elegant*, dan mudah di-*track*, maka ada yang | ||
dinamakan **Design Patterns**. | ||
|
||
## Apa itu Design patterns | ||
|
||
Adalah sebuah solusi agar saat kamu mengemmbangkan sebuah software, | ||
*code* software tersebut mudah dipahami, mudah dikelola, dan memiliki | ||
skalabilitas yang tinggi, bisa buat jaga-jaga jika kamu ingin serius | ||
dengan pengembangan software tersebut. **Design patterns** bukanlah | ||
sebuah *code* yang bisa kamu *plek-ketiplek* salin layaknya algoritma, | ||
melainkan sebuah *template* yang bisa kamu gunakan sebagai acuan saat | ||
mengembangkan software-mu. | ||
|
||
## Kategori Design patterns | ||
|
||
Sebenarnya banyak sekali *patterns* yang digunakan saat proses pengembangan | ||
software, namun ada 23 jenis *patterns* yang umumnya digunakan sebagai pondasi | ||
dari *patterns* lainnya, 23 *patterns* itulah yang umum disebut dengan istilah | ||
**The Gang of Four (GoF)**, **GoF** memiliki 3 kategori, yaitu: | ||
|
||
- *Creational*, adalah bagaimana cara *objects* dibuat. | ||
- [Singleton](singleton/) | ||
- *... TODO* | ||
- *Structural*, adalah bagaimana cara menyusun dan hubungan dari *class-class* mu. | ||
- *... TODO* | ||
- *Behavioral*, adalah bagaimana cara komunikasi antar *objects*. | ||
- *... TODO* | ||
|
||
Bagus dan buruknya *patterns* bersifat *relative* terhadap sesuatu yang kamu | ||
ingin buat atau apa yang ingin kamu selesaikan. | ||
|
||
> [!NOTE] | ||
> disarankan lihat terlebih dahulu [OOP](../object_oriented_programming/) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
cmake_minimum_required(VERSION 3.1) | ||
set (CMAKE_CXX_STANDARD 11) | ||
file( GLOB APP_SOURCES RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} *.cpp ) | ||
foreach( testsourcefile ${APP_SOURCES} ) | ||
string( REPLACE ".cpp" "" testname ${testsourcefile} ) | ||
add_executable( ${testname} ${testsourcefile} ) | ||
|
||
set_target_properties(${testname} PROPERTIES LINKER_LANGUAGE CXX) | ||
if(OpenMP_CXX_FOUND) | ||
target_link_libraries(${testname} OpenMP::OpenMP_CXX) | ||
endif() | ||
install(TARGETS ${testname} DESTINATION "bin/singleton") | ||
|
||
endforeach( testsourcefile ${APP_SOURCES} ) | ||
|
||
file( GLOB FILE_SCOPE_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/static_file_scope/*.cpp" ) | ||
add_executable( "static_file_scope" ${FILE_SCOPE_SOURCES} ) | ||
set_target_properties( "static_file_scope" PROPERTIES LINKER_LANGUAGE CXX ) | ||
if(OpenMP_CXX_FOUND) | ||
target_link_libraries( "static_file_scope" OpenMP::OpenMP_CXX ) | ||
endif() | ||
install( TARGETS "static_file_scope" DESTINATION "bin/singleton" ) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,114 @@ | ||
# Singleton | ||
|
||
Adalah salah satu **Design Pattern** di kategori *Creational*. Sederhananya | ||
*pattern* ini hanya membolehkan sebuah *class* memiliki | ||
**hanya satu instance**, dan *instance* tesebut *Global Accessible* | ||
(artinya *instance* atau *object* tersebut dapat diakses oleh *unit* lain, | ||
atau katakanlah file `.cpp` lain dalam *project* yang sama). Terlepas | ||
dari baik dan buruknya *pattern* ini bisa dibilang banyak digunakan | ||
karena kesederhaannya dan kemudahannya dalam pengaplikasiannya. | ||
|
||
## Kapan menggunakan Singleton ? | ||
|
||
Saat kamu ingin suatu *object* dapat diakses secara global, | ||
dan tidak ada duplikasi dari *object* tersebut. | ||
|
||
## Cara kerja Singleton | ||
|
||
Singleton memiliki `contructor` yang bersifat `private` atau `protected`, | ||
hal ini mencegah *class* tersebut dapat di-insialisasi (dibuat object) secara biasa | ||
(`Class objek;`), lalu bagaimana cara mengakses *object* atau *instance* dari | ||
*class* tersebut ?. Umumnya setiap Singleton memiliki 1 *function* public `static` | ||
dengan return datatype class nya sendiri. [contoh code](singleton_basic.cpp) | ||
|
||
### mengenai `static` keyword | ||
|
||
dalam CPP terdapat 3 kondisi `static` keyword, setiap kondisi dia bertingkah | ||
berbeda baik itu untuk variable ataupun untuk fingsi. | ||
1. ketika digunakan di *file scope*, maka variable tersebut global namun | ||
hanya sebatas dalam file dimana ia di-deklarasikan. [contoh kode](static_file_scope/) | ||
2. ketika digunakan di *function scope*, maka variable tersebut global, | ||
namun hanya bisa diakses oleh atau melalui fungsi tersebut saja. Contohnya | ||
seperti yang [awal-awal](singleton_basic.cpp) | ||
> [!NOTE] | ||
> - variable tersebut belum akan di inisialisasi sampai fungsi tersebut | ||
dipanggil pertama kali. (bagus untuk menghemat resources, namun eksekusi | ||
task kamu akan butuh extra waktu saat eksekusi pertama kali) | ||
> - tidak ada inisialisasi ulang, meskipun fungsi dipanggil beberapa kali | ||
3. ketika digunakan di *struct* atau *class scope*, maka variable tersebut | ||
bukan sembarang member, melainkan member yang global, dapat diakses meskipun | ||
belum dibuat *object*-nya (tergantung level visibilitas), dan setiap *object* | ||
mendapatkan *share* akan variable tersebut (jika *object* kesatu mengubah | ||
nilai variable tersebut maka *object* kedua pun merasakan perubahannya). | ||
Sederhananya variable tersebut milik *class* dan bukan milik *object* | ||
[contoh code](static_class_scope.cpp) | ||
|
||
## Catatan | ||
|
||
Hindari penggunaan Singleton secara berlebihan, contoh saat kamu | ||
ingin cek apakah *Plane* yang dibuat itu memiliki bentuk *square*: | ||
|
||
```cpp | ||
class Plane { | ||
public: | ||
Plane (int x0, int y0, int x1, int y1) { | ||
this->x0 = x0; | ||
this->y0 = y0; | ||
this->x1 = x1; | ||
this->y1 = y1; | ||
} | ||
int x0, y0, x1, y1; | ||
}; | ||
|
||
class PlaneManager { | ||
private: | ||
PlaneManager () = default; | ||
public: | ||
static PlaneManager& getInstance () { | ||
static PlaneManager instance; | ||
return instance; | ||
} | ||
|
||
Plane* createPlane (int x0, int y0, int x1, int y1) { | ||
Plane* plane = new Plane(x0, y0, x1, y1); | ||
return plane; | ||
} | ||
bool isSquareShaped (Plane& plane) { | ||
return (plane.x1 - plane.x0) == (plane.y1 - plane.y0); | ||
} | ||
}; | ||
``` | ||
bagaiman kalau begini | ||
```cpp | ||
class Plane { | ||
public: | ||
Plane (int x0, int y0, int x1, int y1) { | ||
this->x0 = x0; | ||
this->y0 = y0; | ||
this->x1 = x1; | ||
this->y1 = y1; | ||
} | ||
int x0, y0, x1, y1; | ||
bool isSquareShaped() { | ||
return (x1 - x0) == (y1 - y0); | ||
} | ||
}; | ||
``` | ||
|
||
lalu insialisasi objek dengan cara yang biasa, lebih simple | ||
dan masalah terselesaikan. | ||
|
||
## Contoh kode | ||
|
||
- [basic singleton](singleton_basic.cpp) | ||
- [basic singleton 2](singleton_another_example.cpp) | ||
|
||
--- | ||
|
||
- static | ||
- [static di file scope](static_class_scope/) | ||
- [static di function scope](singleton_basic.cpp) | ||
- [static di class scope](static_class_scope.cpp) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
#include <iostream> | ||
|
||
// deklarasi class Logger, sebagai wrapper | ||
class Logger { | ||
protected: | ||
Logger (); | ||
|
||
public: | ||
static Logger& getInstance (); | ||
virtual std::string log (std::string message) = 0; | ||
}; | ||
|
||
// definisi class Logger untuk Windows | ||
class WindowLogger : public Logger { | ||
public: | ||
std::string log(std::string message) override { | ||
// lakukan Windows spesific task | ||
|
||
return "[WINDOWS] INFO: " + message; | ||
} | ||
}; | ||
|
||
// definisi class Logger untuk Unix | ||
class UnixLogger : public Logger { | ||
public: | ||
std::string log(std::string message) override { | ||
// lakukan Unix spesific task | ||
|
||
return "[UNIX] INFO: " + message; | ||
} | ||
}; | ||
|
||
// definisi class Logger | ||
Logger::Logger () = default; | ||
Logger& Logger::getInstance () { | ||
// lazy intialize (di inisialisasi saat fungsi dipanggil pertama kali) | ||
#ifdef _WIN32 | ||
static WindowLogger* instance = new WindowLogger(); | ||
#else | ||
static UnixLogger* instance = new UnixLogger(); | ||
#endif // _WIN32 | ||
return *instance; | ||
} | ||
|
||
int main () { | ||
std::cout << "Logging menggunakan `Logger` class: \n"; | ||
std::cout << "\t" << Logger::getInstance().log("Hello World") << std::endl; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
#include <iostream> | ||
|
||
class Singleton { | ||
private: | ||
Singleton () = default; | ||
|
||
public: | ||
static Singleton& getInstance () { | ||
static Singleton instance; // lazy intialize, memory belum dialokasikan sampai fungsi ini dipanggil pertama kali | ||
return instance; | ||
} | ||
|
||
Singleton (const Singleton& obj) = delete; // mencegah instance assignable | ||
|
||
// definisikan non-static fungsi-fungsi dan variable-variable | ||
// lalu akses seperti biasa. | ||
}; | ||
|
||
// nilai address dari instace Singleton pasti selalu sama, | ||
// yang berarti bahwa object yang dipanggil merupakan object yang sama. | ||
int main () { | ||
std::cout << "Pemanggilan instance pertama: \n"; | ||
std::cout << "\tInstance address: "; | ||
std::cout << &Singleton::getInstance() << '\n'; | ||
|
||
std::cout << "Pemanggilan instance kedua: \n"; | ||
std::cout << "\tInstance address: "; | ||
std::cout << &Singleton::getInstance() << '\n'; | ||
|
||
std::cout << "Pemanggilan instance ketiga: \n"; | ||
std::cout << "\tInstance address: "; | ||
std::cout << &Singleton::getInstance() << '\n'; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
#include <iostream> | ||
|
||
class ClassScope { | ||
public: | ||
ClassScope () = default; | ||
|
||
static int sharedVar; // definisi, memori dialokasikan | ||
}; | ||
|
||
int ClassScope::sharedVar = 5; // insialisasi | ||
|
||
int main () { | ||
ClassScope obj1; | ||
ClassScope obj2; | ||
|
||
std::cout << "Akses langsung nilai variable tanpa perantara object\n"; | ||
std::cout << "\tNilai: " << ClassScope::sharedVar << '\n'; | ||
std::cout << "Akses langsung nilai variable melalui object\n"; | ||
std::cout << "\tNilai: " << obj1.sharedVar << '\n'; | ||
|
||
obj1.sharedVar = 10; | ||
std::cout << "\nObject 1 mengubah nilai variable-nya, menjadi: "; | ||
std::cout << obj1.sharedVar << '\n'; | ||
|
||
std::cout << "Maka object 2 pun merasakan perubahannya\n"; | ||
std::cout << "\tNilai: " << obj2.sharedVar << '\n'; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
static int var = 5; // untuk pembuktian lebih lanjut kamu bisa hilangkan `static` keyword-nya, | ||
// kemudian lakukan kompilasi ulang, | ||
// maka akan muncul error, karena tidah boleh ada 2 global variable (real) | ||
// yang bernama sama. | ||
|
||
// fungsi yang me-return nilai `var` di file ini | ||
int getVar () { | ||
return var; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
#include <iostream> | ||
|
||
extern int getVar(); // deklarasi, memberitahu compiler bahwa fungsi ini di definisikan di file lain | ||
|
||
int var = 10; // intsialisasi global variable (real) | ||
|
||
int main () { | ||
std::cout << "Nilai variable dengan name 'var': "; | ||
std::cout << var << std::endl; | ||
std::cout << "Nilai variable dengan name 'var' di file lain: "; | ||
std::cout << getVar() << std::endl; // tidak bisa akses secara langsung variable `var` | ||
// di file lain karena ekslusif untuk file tersebut saja | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
# Kompilasi | ||
|
||
Compile dengan menjalankan perintah | ||
|
||
```shell | ||
g++ *.cpp -o nama_executable | ||
./nama_executable | ||
``` | ||
atau | ||
|
||
```shell | ||
g++ *.cpp -o nama_executable.exe | ||
.\nama_executable.exe | ||
``` |
Oops, something went wrong.