Featured image of post Sự khác biệt logic giữa bind(), singleton(), scoped() và instance() trong Laravel là gì? Có thể sử dụng trong những tình huống nào?

Sự khác biệt logic giữa bind(), singleton(), scoped() và instance() trong Laravel là gì? Có thể sử dụng trong những tình huống nào?

Sự khác biệt logic giữa bind(), singleton(), scoped() và instance() trong Laravel là gì? Có thể sử dụng trong những tình huống nào?

So sánh các phương thức Binding Object trong Laravel Service Container

Phương thức bind() singleton() scoped() instance()
Mô tả Tạo ra một instance mới mỗi khi được giải quyết (resolved). Chỉ tạo một instance duy nhất và trả về cùng một instance đó trong các yêu cầu tiếp theo. Chỉ tạo một instance duy nhất trong mỗi vòng đời yêu cầu/công việc (request/job lifecycle), instance này sẽ bị xóa sau khi yêu cầu kết thúc. Gắn (bind) một instance đã tồn tại vào container và trả về instance đó mỗi khi được giải quyết.
Ưu điểm - Một instance hoàn toàn mới cho mỗi yêu cầu, không có vấn đề chia sẻ trạng thái
- Sử dụng bộ nhớ sạch sẽ
- Thích hợp cho logic yêu cầu trạng thái độc lập
- Có thể cung cấp cấu hình duy nhất cho mỗi yêu cầu
- Tiết kiệm tài nguyên hệ thống bằng cách chỉ tạo instance một lần
- Đảm bảo tính nhất quán của trạng thái
- Thích hợp để chia sẻ cấu hình và tài nguyên
- Hiệu suất tốt hơn trong tình huống truy cập đồng thời cao (high concurrency)
- Cân bằng giữa việc sử dụng bộ nhớ và chia sẻ trạng thái
- Chia sẻ trạng thái trong một yêu cầu nhưng bị cô lập giữa các yêu cầu
- Thích hợp cho các kịch bản Web Request
- Kiểm soát hoàn toàn thời điểm tạo instance
- Có thể cấu hình trước trạng thái của instance
- Thích hợp cho các dịch vụ yêu cầu cấu hình cụ thể
Nhược điểm - Cần nhiều tài nguyên hệ thống hơn để tạo instance lặp đi lặp lại
- Có thể ảnh hưởng đến hiệu suất khi truy cập đồng thời cao
- Không thích hợp cho các kịch bản yêu cầu chia sẻ trạng thái
- Có thể gây ra vấn đề hiệu suất vì instance mới được tạo mỗi lần.
- Trạng thái chia sẻ có thể dẫn đến các lỗi khó theo dõi
- Không thích hợp cho các kịch bản yêu cầu trạng thái độc lập
- Việc chiếm dụng bộ nhớ kéo dài đến khi chương trình kết thúc
- Kiểm thử cần chú ý đặc biệt đến việc đặt lại trạng thái
- Nếu instance đó giữ trạng thái, nó có thể gây ra hành vi không mong muốn.
- Có thể gây ra vấn đề trong các tác vụ chạy dài
- Cần hiểu vòng đời yêu cầu
- Không thích hợp cho các lệnh CLI
- Ít linh hoạt hơn
- Không thể điều chỉnh cấu hình instance một cách động
- Có thể chiếm bộ nhớ khi khởi động
- Không thích hợp cho các trường hợp yêu cầu lazy loading hoặc nhiều instance.
Trường hợp sử dụng Dùng cho các dịch vụ sử dụng ngắn hạn hoặc các lớp (class) yêu cầu trạng thái độc lập. Dùng cho các dịch vụ được chia sẻ toàn cầu, như logger hoặc trình quản lý cấu hình. Dùng cho các dịch vụ cần duy trì trạng thái trong một yêu cầu nhưng không muốn duy trì qua các yêu cầu khác, như kết nối cơ sở dữ liệu. Khi bạn đã có một instance và muốn sử dụng lại nó, như đối tượng cấu hình được chia sẻ.
Ví dụ Khi bạn có một lớp Product và muốn tạo một instance Product mới mỗi khi dữ liệu sản phẩm khác nhau được yêu cầu. Khi bạn có một lớp Logger và muốn tất cả các thao tác ghi log sử dụng cùng một instance để duy trì tính nhất quán. Khi bạn có một lớp ShoppingCart và cần chia sẻ trạng thái giỏ hàng trong cùng một yêu cầu. Khi bạn có một lớp DatabaseConfig và cần thiết lập các tham số kết nối khi ứng dụng khởi động.

Ví dụ

Sử dụng bind()

$this->app->bind('Product', function () {
 return new Product();
});

Mỗi khi gọi app('Product'), nó sẽ trả về một instance Product mới.

Sử dụng singleton()

$this->app->singleton('Logger', function () {
 return new Logger();
});

Mỗi khi gọi app('Logger'), nó sẽ trả về cùng một instance Logger.

Sử dụng scoped()

$this->app->scoped(Transistor::class, function (Application $app) {
    return new Transistor($app->make(PodcastParser::class));
});

Chia sẻ cùng một instance trong cùng một vòng đời yêu cầu; các yêu cầu khác nhau sẽ tạo ra các instance mới.

Sử dụng instance()


$service = new Transistor(new PodcastParser);
 
$this->app->instance(Transistor::class, $service);

Gắn trực tiếp một instance đã tồn tại vào container.

Tóm tắt

Laravel hiện có thể được áp dụng trong nhiều loại kịch bản khác nhau, như Web Request, CLI Command, Queue Job, Console Command, v.v.

Vì vậy, khi chọn phương thức binding nào để sử dụng, bạn cần xem xét nhu cầu của dịch vụ trong các kịch bản khác nhau, cũng như việc bạn có cần chia sẻ trạng thái hay cấu hình hay không.

Reference

All rights reserved,未經允許不得隨意轉載
Built with Hugo
Theme Stack thiết kế bởi Jimmy