Khởi tạo lười biếng của các đối tượng là gì? Làm thế nào để bạn làm điều đó và những lợi thế là gì?
Câu trả lời:
Lazy Initialization là một tối ưu hóa hiệu suất trong đó bạn trì hoãn việc tạo đối tượng (có thể tốn kém) cho đến ngay trước khi bạn thực sự cần nó.
Một ví dụ điển hình là không tạo kết nối cơ sở dữ liệu trước mà chỉ tạo ngay trước khi bạn cần lấy dữ liệu từ cơ sở dữ liệu.
Lý do chính để làm điều này là (thường xuyên) bạn có thể tránh hoàn toàn việc tạo đối tượng nếu bạn không bao giờ cần đến nó.
Lazyđược đăng trong câu hỏi SO sau: stackoverflow.com/a/15894928/4404962 gợi ý này đã giải quyết chính xác những gì chúng tôi cần giải quyết - sử dụng Lazylàm khóa chính
Như những người khác đã đề cập, khởi tạo lười biếng đang trì hoãn việc khởi tạo cho đến khi một thành phần hoặc đối tượng được sử dụng. Bạn có thể xem khởi tạo lười biếng như một ứng dụng thời gian chạy của nguyên tắc YAGNI - " You ain't gonna need it"
Ưu điểm từ góc độ ứng dụng của khởi tạo lười biếng là người dùng không phải trả thời gian khởi tạo cho các tính năng mà họ sẽ không sử dụng. Giả sử bạn đã khởi tạo mọi thành phần của ứng dụng của mình từ trước. Điều này có thể tạo ra một thời gian bắt đầu dài có thể xảy ra - người dùng sẽ phải đợi hàng chục giây hoặc vài phút trước khi ứng dụng của bạn sẵn sàng sử dụng. Họ đang chờ đợi và trả tiền để khởi tạo các tính năng mà họ có thể không bao giờ sử dụng hoặc không sử dụng ngay.
Thay vào đó, nếu bạn trì hoãn việc khởi tạo các thành phần đó cho đến khi sử dụng, ứng dụng của bạn sẽ khởi động nhanh hơn nhiều. Người dùng sẽ vẫn phải trả chi phí khởi động khi sử dụng các thành phần khác, nhưng chi phí đó sẽ được phân bổ trong quá trình chạy chương trình và không được cô đọng vào đầu và người dùng có thể liên kết thời gian khởi tạo của các đối tượng này với các tính năng của chúng. đang sử dụng.
Lazy Initialization là khái niệm trì hoãn việc tạo đối tượng cho đến khi đối tượng thực sự được sử dụng lần đầu tiên. Nếu được sử dụng đúng cách, nó có thể mang lại hiệu suất đáng kể.
Cá nhân tôi đã sử dụng Lazy Initialization khi tạo ORM cuộn thủ công của riêng mình trong .NET 2.0. Khi tải bộ sưu tập của tôi từ cơ sở dữ liệu, các mục thực tế trong bộ sưu tập đã được khởi tạo lười biếng. Điều này có nghĩa là các bộ sưu tập được tạo nhanh chóng, nhưng mỗi đối tượng chỉ được tải khi tôi yêu cầu.
Nếu bạn đã quen thuộc với mẫu Singleton, bạn cũng có thể thấy quá trình khởi tạo lười biếng đang hoạt động.
public class SomeClassSingleton
{
private static SomeClass _instance = null;
private SomeClassSingleton()
{
}
public static SomeClass GetInstance()
{
if(_instance == null)
_instance = new SomeClassSingleton();
return _instance;
}
}
Trong trường hợp này, phiên bản của SomeClass không được khởi tạo cho đến khi người tiêu dùng SomeClassSingleton cần nó lần đầu tiên.
Theo thuật ngữ máy tính chung, 'đánh giá lười biếng' có nghĩa là trì hoãn việc xử lý một thứ gì đó cho đến khi bạn thực sự cần nó. Ý tưởng chính là đôi khi bạn có thể tránh các hoạt động tốn kém nếu bạn không cần đến nó hoặc nếu giá trị sẽ thay đổi trước khi bạn sử dụng nó.
Một ví dụ đơn giản về điều này là System.Exception.StackTrace. Đây là một thuộc tính chuỗi trên một ngoại lệ, nhưng nó không thực sự được xây dựng cho đến khi bạn truy cập vào nó. Bên trong nó hoạt động như sau:
String StackTrace{
get{
if(_stackTrace==null){
_stackTrace = buildStackTrace();
}
return _stackTrace;
}
}
Điều này giúp bạn tiết kiệm chi phí thực sự gọi buildStackTrace cho đến khi ai đó muốn xem nó là gì.
Thuộc tính là một cách đơn giản để cung cấp loại hành vi này.
Ở đây bạn có thể đọc về Khởi tạo Lazy với mã mẫu.
Khi bạn có một đối tượng tốn kém để tạo và chương trình có thể không sử dụng nó. Ví dụ: giả sử rằng bạn có trong bộ nhớ một đối tượng Khách hàng có thuộc tính Đơn hàng có chứa một mảng lớn các đối tượng Đơn hàng, để được khởi tạo, yêu cầu kết nối cơ sở dữ liệu. Nếu người dùng không bao giờ yêu cầu hiển thị Đơn đặt hàng hoặc sử dụng dữ liệu trong tính toán, thì không có lý do gì để sử dụng bộ nhớ hệ thống hoặc chu trình tính toán để tạo ra nó. Bằng cách sử dụng Lazy để khai báo đối tượng Đơn hàng cho quá trình khởi tạo lười biếng, bạn có thể tránh lãng phí tài nguyên hệ thống khi đối tượng không được sử dụng.
Khi bạn có một đối tượng tốn kém để tạo và bạn muốn trì hoãn việc tạo đối tượng đó cho đến khi hoàn thành các thao tác tốn kém khác. Ví dụ: giả sử rằng chương trình của bạn tải một số cá thể đối tượng khi nó khởi động, nhưng chỉ một số trong số chúng được yêu cầu ngay lập tức. Bạn có thể cải thiện hiệu suất khởi động của chương trình bằng cách trì hoãn khởi tạo các đối tượng không được yêu cầu cho đến khi các đối tượng cần thiết đã được tạo.
Khởi tạo lười biếng của một đối tượng có nghĩa là việc tạo ra nó bị hoãn lại cho đến khi nó được sử dụng lần đầu tiên. (Đối với chủ đề này, thuật ngữ khởi tạo lười biếng và khởi tạo lười biếng đồng nghĩa với nhau.) Khởi tạo lười biếng chủ yếu được sử dụng để cải thiện hiệu suất, tránh tính toán lãng phí và giảm yêu cầu bộ nhớ chương trình. Đây là những tình huống phổ biến nhất:
Khi bạn có một đối tượng tốn kém để tạo và chương trình có thể không sử dụng nó. Ví dụ: giả sử rằng bạn có trong bộ nhớ một đối tượng Khách hàng có thuộc tính Đơn hàng có chứa một mảng lớn các đối tượng Đơn hàng, để được khởi tạo, yêu cầu kết nối cơ sở dữ liệu. Nếu người dùng không bao giờ yêu cầu hiển thị Đơn đặt hàng hoặc sử dụng dữ liệu trong tính toán, thì không có lý do gì để sử dụng bộ nhớ hệ thống hoặc chu trình tính toán để tạo ra nó. Bằng cách sử dụng Lazy để khai báo đối tượng Đơn hàng cho quá trình khởi tạo lười biếng, bạn có thể tránh lãng phí tài nguyên hệ thống khi đối tượng không được sử dụng.
Khi bạn có một đối tượng tốn kém để tạo và bạn muốn trì hoãn việc tạo đối tượng đó cho đến khi hoàn thành các thao tác tốn kém khác. Ví dụ: giả sử rằng chương trình của bạn tải một số cá thể đối tượng khi nó khởi động, nhưng chỉ một số trong số chúng được yêu cầu ngay lập tức. Bạn có thể cải thiện hiệu suất khởi động của chương trình bằng cách trì hoãn khởi tạo các đối tượng không được yêu cầu cho đến khi các đối tượng cần thiết đã được tạo.
Mặc dù bạn có thể viết mã của riêng mình để thực hiện khởi tạo lười biếng, chúng tôi khuyên bạn nên sử dụng Lazy thay thế. Lazy và các loại liên quan của nó cũng hỗ trợ an toàn luồng và cung cấp một chính sách lan truyền ngoại lệ nhất quán.
//Lazy instantiation delays certain tasks.
//It typically improves the startup time of a C# application.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace LazyLoad
{
class Program
{
static void Main(string[] args)
{
Lazy<MyClass> MyLazyClass = new Lazy<MyClass>(); // create lazy class
Console.WriteLine("IsValueCreated = {0}",MyLazyClass.IsValueCreated); // print value to check if initialization is over
MyClass sample = MyLazyClass.Value; // real value Creation Time
Console.WriteLine("Length = {0}", sample.Length); // print array length
Console.WriteLine("IsValueCreated = {0}", MyLazyClass.IsValueCreated); // print value to check if initialization is over
Console.ReadLine();
}
}
class MyClass
{
int[] array;
public MyClass()
{
array = new int[10];
}
public int Length
{
get
{
return this.array.Length;
}
}
}
}
// out put
// IsValueCreated = False
// Length = 10
// IsValueCreated = True
Như những gì tôi đã hiểu về lazy init cho đến nay, là chương trình không tải / yêu cầu tất cả dữ liệu cùng một lúc. Nó đợi việc sử dụng nó trước khi yêu cầu nó từ ví dụ. một máy chủ SQL.
Nếu bạn có một cơ sở dữ liệu với một bảng lớn được kết hợp với một số lượng lớn các bảng phụ và bạn không yêu cầu các chi tiết được nối từ các tab khác trừ khi đi vào "chỉnh sửa" hoặc "xem chi tiết", thì Lazy Init. sẽ giúp ứng dụng chạy nhanh hơn và trước tiên hãy "tải chậm" dữ liệu chi tiết khi cần.
Trong SQL hoặc LINQ, bạn có thể đặt "cài đặt" này trên pr mô hình cơ sở dữ liệu của mình. tăng tốc dữ liệu.
Hy vọng điều này có ý nghĩa đối với câu hỏi của bạn?
Webclient (ví dụ: trình duyệt) cũng làm điều tương tự. Các hình ảnh được "tải lười biếng" sau HTML và AJAX cũng là một "loại init lười biếng" nếu được sử dụng đúng cách.
Các ví dụ cơ sở dữ liệu đã được đề cập cho đến nay là tốt, nhưng nó không bị giới hạn ở chỉ lớp truy cập dữ liệu. Bạn có thể áp dụng các nguyên tắc tương tự cho bất kỳ tình huống nào mà hiệu suất hoặc bộ nhớ có thể là mối quan tâm. Một ví dụ điển hình (mặc dù không phải .NET) là trong Cocoa, nơi bạn có thể đợi cho đến khi người dùng yêu cầu một cửa sổ thực sự tải nó (và các đối tượng liên quan của nó) từ ngòi. Điều này có thể giúp giảm mức sử dụng bộ nhớ và tăng tốc độ tải ứng dụng ban đầu, đặc biệt khi bạn đang nói về những thứ như cửa sổ Tùy chọn sẽ không cần thiết cho đến một thời gian sau, nếu có.