Skip to content

Commit

Permalink
Merge branch 'bellshade:main' into aj
Browse files Browse the repository at this point in the history
  • Loading branch information
yusuf601 authored Jan 14, 2025
2 parents bb0aee5 + ffb5dbe commit 027eacb
Show file tree
Hide file tree
Showing 12 changed files with 436 additions and 1 deletion.
1 change: 1 addition & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ add_subdirectory(artificial_intelligence)
add_subdirectory(strings)
add_subdirectory(geometri)
add_subdirectory(graf)
add_subdirectory(design_patterns/singleton)

# FIXME: ada beberapa fungsi header math terkhusus untuk
# windows, oleh karena itu maka setting kompilasi
Expand Down
2 changes: 1 addition & 1 deletion basic/04_operator/readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ Operator Bitwise adalah operator yang melakukan operasi pada level bit (biner) d
Operator ini bekerja dengan mengoperasikan bit per bit dari dua operand.

| Operator | Nama Operasi | Keterangan |
| - | - | - |h
| - | - | - |
| `&` | AND | Menghasilkan 1 jika kedua bit bernilai 1 |
| `\|` | OR | Menghasilkan 1 jika salah satu bit bernilai 1 |
| `^` | XOR | Menghasilkan 1 jika kedua bit bernilai berbeda |
Expand Down
38 changes: 38 additions & 0 deletions design_patterns/readme.md
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/)
22 changes: 22 additions & 0 deletions design_patterns/singleton/CMakeLists.txt
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" )
114 changes: 114 additions & 0 deletions design_patterns/singleton/readme.md
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)
48 changes: 48 additions & 0 deletions design_patterns/singleton/singleton_another_example.cpp
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;
}
33 changes: 33 additions & 0 deletions design_patterns/singleton/singleton_basic.cpp
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';
}
27 changes: 27 additions & 0 deletions design_patterns/singleton/static_class_scope.cpp
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';
}
9 changes: 9 additions & 0 deletions design_patterns/singleton/static_file_scope/another.cpp
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;
}
13 changes: 13 additions & 0 deletions design_patterns/singleton/static_file_scope/main.cpp
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
}
14 changes: 14 additions & 0 deletions design_patterns/singleton/static_file_scope/readme.md
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
```
Loading

0 comments on commit 027eacb

Please sign in to comment.