Factory Pattern là một trong những design pattern quan trọng giúp code linh hoạt, dễ mở rộng và dễ bảo trì. Trong thực tế, đặc biệt khi làm việc với Laravel, bạn gần như đang sử dụng Factory mỗi ngày mà không để ý. Bài này sẽ giúp bạn hiểu từ bản chất → cách viết → cách áp dụng chuẩn production.
Factory Pattern là một design pattern dùng để:
Tách việc khởi tạo object ra khỏi nơi sử dụng object
Thay vì tạo object trực tiếp bằng new, bạn sẽ thông qua một lớp trung gian gọi là Factory.
Giả sử bạn viết code như sau:
$cache = new RedisCache();
👉 Đây gọi là tight coupling
Bạn tạo một lớp Factory:
class CacheFactory {
public static function make() {
return new RedisCache();
}
}
Sử dụng:
$cache = CacheFactory::make();
Factory không phải chỉ là “thêm 1 lớp”
👉 Nó giải quyết 3 vấn đề cốt lõi:
Toàn bộ logic khởi tạo nằm ở một nơi duy nhất
return new RedisCache(
new Connection(...),
new Logger(...),
config(...)
);
Bên ngoài chỉ cần:
CacheFactory::make();
if ($driver === 'redis') {
return new RedisCache();
}if ($driver === 'file') {
return new FileCache();
}
👉 Code bên ngoài không cần sửa
interface CacheInterface {
public function get($key);
}
class RedisCache implements CacheInterface {
public function get($key) {
return "redis: " . $key;
}
}class FileCache implements CacheInterface {
public function get($key) {
return "file: " . $key;
}
}
class CacheFactory {
public static function make($driver): CacheInterface {
return match ($driver) {
'redis' => new RedisCache(),
'file' => new FileCache(),
default => throw new Exception("Driver not supported")
};
}
}
$cache = CacheFactory::make('redis');
echo $cache->get('user');
Trong Laravel, Factory xuất hiện ở rất nhiều nơi:
Cache::store('redis');
Cache::store('file');
👉 Laravel dùng Factory để tạo driver tương ứng
DB::connection('mysql');
DB::connection('pgsql');
👉 Mỗi connection là một object khác nhau được tạo qua factory
User::factory()->create();
👉 Tạo dữ liệu test mà không cần new thủ công
Bạn nên dùng Factory khi:
Không muốn code phụ thuộc class cụ thể
Có thể mock factory hoặc interface
Không phải lúc nào cũng dùng Factory
👉 Tránh khi:
| Cách | Đặc điểm |
|---|---|
| new trực tiếp | nhanh nhưng cứng |
| Factory | linh hoạt, dễ mở rộng |
Đây là điểm nhiều dev nhầm:
CacheFactory::make('redis');
public function __construct(CacheInterface $cache)
👉 Laravel tự inject từ container
Factory Pattern không chỉ là “tạo thêm 1 lớp”, mà là một abstraction quan trọng giúp:
👉 Nếu nói theo kiểu senior:
Factory Pattern giúp centralize object creation, giảm coupling và hỗ trợ mở rộng theo nguyên lý Open Closed.