Dependency Inversion
The Dependency Inversion Principle states that high-level modules should depend on abstractions (interfaces), not concrete implementations. This makes code testable and swappable.
The Dependency Inversion Principle states that high-level modules should depend on abstractions (interfaces), not concrete implementations. This makes code testable and swappable.
<?php
// Abstraction (interface)
interface CacheInterface {
public function get(string $key): mixed;
public function set(string $key, mixed $value, int $ttl = 3600): void;
public function forget(string $key): void;
}
// Two implementations
class RedisCache implements CacheInterface { /* ... */ }
class ArrayCache implements CacheInterface { /* ... */ } // for tests
// High-level module depends on interface, not concrete class
class ProductService {
public function __construct(private CacheInterface $cache) {}
public function getProduct(int $id): array {
$key = "product:{$id}";
$cached = $this->cache->get($key);
if ($cached !== null) return $cached;
// ... fetch from DB ...
$this->cache->set($key, $product);
return $product;
}
}
Dependency Injection Containers (like Laravel's service container) automatically resolve interface bindings to their concrete implementations.