Konsep dasar dan implementasi pada PHP/Laravel
Singleton design pattern adalah design pattern sederhana yang juga biasa disebut sebagai Singleton. Pada Object Oriented Programming (OOP), biasanya diterapkan pada modul yang hanya membutuhkan satu instance dalam keseluruhan operasi dari program, seperti contohnya modul koneksi database, atau modul untuk komunikasi dengan eksternal API services.
Pengenalan
Pengertian
Singleton adalah salah satu design pattern yang masuk ke dalam jenis creational design pattern. Creational design pattern adalah design pattern yang fokus utamanya ada pada cara pembuatan objek untuk meningkatkan fleksibilitas dan penggunaan kembali kode yang ada (reuse of existing code). Singleton memastikan bahwa satu class hanya bisa memiliki satu instance.
Struktur
Implementasi dari Singleton terletak pada class yang dibuat menjadi Singleton class yang mana pada umumnya memiliki dua ciri umum :
- Access modifier pada constructor yang asli adalah private, untuk mencegah pembuatan instance menggunakan operator
new
pada Singleton class. - Ada static method yang bertindak sebagai constructor untuk membuat instance. Pada method ini dilakukan pemanggilan private constructor untuk menciptakan objek lalu menyimpannnya dalam variable static. Kemudiaan semua pemanggilan terhadap method ini setelahnya akan mengembalikan objek dari variabel tadi.
Berikut adalah class diagram yang menggambarkan property dan method yang harus ada pada sebuah Singleton class :
Contoh implementasi dalam bahasa PHP adalah sebagai berikut :
// Singleton Class
Class Singleton
{
private static Singleton $instance;
/**
* Privated contructer to prevent instantiation from outside of class
*/
private function __construct() { }
/**
* The method to get singleton instance.
*/
public static function getInstance(): Singleton
{
if (!isset(self::$instance)) {
self::$instance = new static();
}
return self::$instance;
}
}
// Usage Example (Client Code)
function clientCode()
{
$s1 = Singleton::getInstance();
$s2 = Singleton::getInstance();
if ($s1 === $s2) {
echo "Singleton works, both variables contain the same instance.";
} else {
echo "Singleton failed, variables contain different instances.";
}
}
clientCode();
Kelebihan
- Sebuah class pasti hanya memiliki satu instance.
- Bisa mendapatkan akses kepada instance secara global.
- Objek singleton diinisialisasi hanya ketika pertama kali dibutuhkan
Kekurangan
- Memungkinkan untuk menyembunyikan desain yang buruk, contohnya suatu komponen mengetahui terlalu banyak tentang komponen lainnya.
- Membutuhkan penanganan khusus dalam lingkungan multithread agar tidak menciptakan objek singleton beberapa kali.
Penggunaan
- Singleton pattern bisa digunakan ketika class dalam program hanya perlu memiliki satu intance untuk berbagai keperluan. Contohnya adalah untuk objek basis data yang digunakan bersama oleh berbagai bagian dari program.
- Singleton pattern bisa digunakan ketika butuh kontrol yang lebih terhadap variabel - variabel global.
Implementasi
Dependency Injection
Pada laravel, banyak diterapkan dependency injection (DI) untuk membuat sebuah objek dari sebuah class ketika class tersebut dibutuhkan pada class lainnya. Interface bisa digunakan sebagai abstraction dan class sebagai concrete implementation.
Service Container
Service Container bisa digunakan untuk mengelola dependensi dan melakukan dependency injection. DI dilakukan melalui binding atau “menyambungkan” dari satu class / interface kepada class lainnya atau abstract kepada implementation. Hampir semua binding dalam service container dikonfigurasi pada Service Provider.
Berikut adalah beberapa macam binding yang biasa digunakan :
- Simple Binding
Melakukan binding dari abstract (class atau interface) yang akan membuat instance baru dari class setiap kali abstact dipanggil.
2. Binding Singleton
Melakukan binding dari abstract (class atau interface) yang akan mengembalikan instance yang sama dengan instance yang sebelumnya pernah dibuat (resolved) saat pertama kali abstract dipanggil.
Code Example
- Interface
Interface berfungsi sebagai abstraction dari class.
<?php
namespace App\Interfaces;
interface PostDataInterface
{
/**
* List resource.
*
* @return array
*/
public function list(): array;
/**
* Get Selected resource.
*
* @return object
*/
public function selected(int $id): object;
}
2. “Singleton” Class
Class yang akan dibuat menjadi singleton dengan binding singleton.
<?php
namespace App\Services;
use App\Interfaces\PostDataInterface;
use Illuminate\Database\Eloquent\ModelNotFoundException;
use Illuminate\Support\Facades\Http;
use Symfony\Component\HttpKernel\Exception\HttpException;
class PostDataService implements PostDataInterface
{
private $client;
public function __construct()
{
$this->client = Http::baseUrl(config('services.post.url'));
}
public function list(): array
{
$response = $this->client->get('/posts');
if ($response->successful()) {
return $response->object();
}
throw New HttpException('400', 'Bad Request');
}
public function selected(int $id): object
{
$response = $this->client->get('/posts/' . $id);
if ($response->successful()) {
return $response->object();
}
throw new ModelNotFoundException();
}
}
3. Service Provider
Service Provider untuk melakukan konfigurasi binding.
<?php
namespace App\Providers;
use App\Interfaces\PostDataInterface;
use App\Services\PostDataService;
use Illuminate\Support\ServiceProvider;
class PostDataServiceProvider extends ServiceProvider
{
/**
* Register services.
*
* @return void
*/
public function register()
{
$this->app->singleton(PostDataInterface::class, PostDataService::class);
}
/**
* Bootstrap services.
*
* @return void
*/
public function boot()
{
//
}
}
4. App Config
Setelah dibuat, Service Provider perlu didaftarkan pada app config.
<?php
....
/*
* Application Service Providers...
*/
App\Providers\AppServiceProvider::class,
App\Providers\AuthServiceProvider::class,
// App\Providers\BroadcastServiceProvider::class,
App\Providers\EventServiceProvider::class,
App\Providers\PostDataServiceProvider::class, // <-- Add this
App\Providers\RouteServiceProvider::class,
...
5. Controller
Contoh penggunaan Singleton class.
<?php
namespace App\Http\Controllers;
use App\Http\Resources\PostDataResource;
use App\Interfaces\PostDataInterface;
class PostController extends Controller
{
private PostDataInterface $postDataService;
public function __construct(PostDataInterface $postDataService)
{
$this->postDataService = $postDataService;
}
/**
* Display a listing of the resource.
*
* @return \Illuminate\Http\Response
*/
public function index()
{
$response = $this->postDataService->list();
return PostDataResource::collection($response);
}
/**
* Display the specified resource.
*
* @param int $id
* @return \Illuminate\Http\Response
*/
public function show($id)
{
$response = $this->postDataService->selected($id);
return new PostDataResource($response);
}
}
Penutup
Kata Penutup
Singleton adalah design pattern yang bisa diterapkan pada modul program yang hanya membutuhkan satu instance dari class-nya. Ada kontrol yang lebih terhadap variabel global dan tidak perlu melakukan pembuatan objek setiap kali modul dipanggil. Semoga tulisan kali ini bermanfaat. Sampai jumpa di tulisan selanjutnya. Salam.