Mục lục:

Cách thực hiện mẫu thiết kế Singleton trong C ++: 9 bước
Cách thực hiện mẫu thiết kế Singleton trong C ++: 9 bước

Video: Cách thực hiện mẫu thiết kế Singleton trong C ++: 9 bước

Video: Cách thực hiện mẫu thiết kế Singleton trong C ++: 9 bước
Video: Kỹ thuật lập trình với Python - Bài 7: Kiểm thử, Gỡ lỗi, Biệt lệ và Assertion 2024, Tháng mười một
Anonim
Cách thực hiện mẫu thiết kế Singleton trong C ++
Cách thực hiện mẫu thiết kế Singleton trong C ++

Giới thiệu:

Mục đích của hướng dẫn này là để dạy người dùng cách triển khai mẫu thiết kế singleton trong chương trình C ++ của họ. Khi làm như vậy, tập hướng dẫn này cũng sẽ giải thích cho người đọc tại sao các phần tử của một singleton lại giống như chúng và cách mã được xử lý. Biết được điều này, sẽ giúp ích trong việc gỡ lỗi các đĩa đơn trong tương lai của bạn. Mô hình thiết kế singleton là gì? Mẫu thiết kế singleton là một mẫu thiết kế trong đó người lập trình tạo một lớp chỉ có thể được khởi tạo một lần, các chức năng công khai của lớp về cơ bản có thể được truy cập ở bất kỳ đâu, miễn là bạn có #included tệp tiêu đề trong các tệp khác có liên quan đến dự án.

Mẫu thiết kế singleton là mẫu thiết kế phải biết đối với bất kỳ lập trình viên hướng đối tượng, lập trình viên phần mềm và lập trình trò chơi nào. Mẫu thiết kế singleton cũng là một trong những mẫu thiết kế mã hóa dễ dàng nhất hiện có. Học nó có thể giúp bạn học các mẫu thiết kế khác, khó hơn, trong tương lai. Nó cũng có thể giúp bạn sắp xếp hợp lý mã chương trình của mình theo những cách bạn không nghĩ là có thể.

Trong khi độ khó của mẫu thiết kế singleton là dễ so với các mẫu thiết kế khác, tập hướng dẫn này có độ khó trung bình. Điều này có nghĩa là để thực hiện các hướng dẫn này, chúng tôi khuyên bạn nên biết các yêu cầu cơ bản và nâng cao về cú pháp của C ++. Bạn cũng nên biết các nghi thức viết mã C ++ thích hợp (tức là giữ các biến lớp ở chế độ riêng tư, một lớp cho mỗi tệp tiêu đề, v.v.). Bạn cũng nên biết cách giải phóng bộ nhớ và cách thức hoạt động của các hàm tạo và hàm hủy trong C ++.

Hướng dẫn này sẽ mất trung bình khoảng 10-15 phút.

Yêu cầu vật liệu:

-Một máy tính (có thể là PC hoặc Mac) có khả năng chạy Visual Studios (bất kỳ phiên bản nào)

-Một chương trình đơn giản, được tạo trong Visual Studios, mà bạn có thể kiểm tra singleton của mình với

Lưu ý: Mẫu thiết kế singleton có thể được thực hiện trên bất kỳ giao diện mã hóa hoặc IDE hỗ trợ C ++ nào khác, nhưng đối với tập hướng dẫn này, chúng tôi sẽ sử dụng Visual Studios Enterprise Edition.

Bước 1: Tạo Lớp học của Bạn, Với Tệp Tiêu đề và Tệp CPP

Tạo lớp học của bạn, với tệp tiêu đề và tệp CPP
Tạo lớp học của bạn, với tệp tiêu đề và tệp CPP
Tạo Lớp học của Bạn, Với Tệp Tiêu đề và Tệp CPP
Tạo Lớp học của Bạn, Với Tệp Tiêu đề và Tệp CPP

Để tạo hai tệp này và cả lớp cùng một lúc, hãy mở dự án / chương trình của bạn trong Visual Studios, chuyển đến trình khám phá giải pháp, nhấp chuột phải và một hộp sẽ hiển thị gần con trỏ chuột của bạn, tìm tùy chọn “Thêm”, di chuột trên nó, và một hộp khác sẽ xuất hiện ở bên phải. Trong hộp này, bạn muốn tìm tùy chọn “New Item..”, hãy nhấp vào nó và một cửa sổ, giống như hình ảnh 1.1 bên dưới, sẽ xuất hiện. Trong cửa sổ này, bạn muốn chọn “Lớp C ++” và sau đó nhấn “Thêm”. Thao tác này sẽ mở ra một cửa sổ khác giống như hình ảnh 1.2. Trong cửa sổ này, bạn nhập tên lớp của mình vào trường “Tên lớp” và Visual Studios sẽ tự động đặt tên tệp thực sau tên lớp. Đối với mục đích của hướng dẫn này, chúng tôi sẽ đặt tên cho lớp của chúng tôi là “EngineDebugSingleton”, nhưng nó có thể là bất kỳ tên dựa trên chữ cái nào. Bây giờ bạn có thể nhấn “OK” và tiếp tục bước 2.

Lưu ý: Trình khám phá giải pháp và nơi các tệp được lưu trên máy tính của bạn là riêng biệt. Di chuyển hoặc tạo bất kỳ thứ gì trong trình khám phá giải pháp sẽ không di chuyển hoặc sắp xếp các tệp trong trình khám phá tệp hệ điều hành của bạn. Một cách an toàn để sắp xếp các tệp của bạn ở phía trình khám phá tệp sẽ bị xóa, nhưng không xóa các tệp cụ thể khỏi trình khám phá giải pháp, hãy di chuyển các tệp tương tự trong trình khám phá tệp đến vị trí mong muốn và sau đó quay lại trình khám phá giải pháp, nhấp chuột phải, tìm tùy chọn “Thêm”, sau đó tìm “Mục hiện có” và tìm các tệp bạn đã di chuyển. Đảm bảo rằng bạn di chuyển cả tiêu đề và tệp cpp.

Bước 2: Đặt Constructor thành Riêng tư

Đặt Constructor thành Riêng tư
Đặt Constructor thành Riêng tư

Với tệp tiêu đề và tệp CPP mới tạo của bạn, nếu tệp không tự động mở khi bạn tạo, hãy chuyển đến trình khám phá giải pháp và nhấp và mở “EngineDebugSingleton.h”. Sau đó, bạn sẽ được chào đón bằng một “EngineDebugSingleton ()”, hàm tạo mặc định của lớp và “~ EngineDebugSingleton ()” là hàm hủy của lớp. Đối với bước này, chúng ta sẽ muốn đặt hàm tạo thành private, điều này có nghĩa là hàm này chỉ có sẵn cho lớp và không có gì khác. Với điều này, bạn sẽ không thể tạo biến hoặc cấp phát lớp vào bộ nhớ bên ngoài lớp, chỉ trong tệp tiêu đề của lớp và các hàm khác của lớp. Có hàm tạo riêng là chìa khóa cho mẫu thiết kế và cách các singleton hoạt động. Chúng tôi sẽ khám phá trong các bước tương lai cách một singleton được khởi tạo và truy cập.

Lớp bây giờ sẽ trông như thế này sau khi chuyển hàm tạo sang private (Xem ảnh được liên kết)

Bước 3: Đặt Trình hủy thành Riêng tư

Đặt Trình hủy thành Riêng tư
Đặt Trình hủy thành Riêng tư

Giống như chúng ta đã làm với hàm tạo trong

bước 2, đối với bước này, bây giờ chúng ta sẽ đặt hàm hủy thành riêng tư. Giống như với hàm tạo, không có gì, ngoại trừ chính lớp, sẽ có thể xóa bất kỳ biến nào của lớp khỏi bộ nhớ.

Bây giờ lớp sẽ trông như thế này sau khi hoàn thành bước này. (Xem ảnh liên quan)

Bước 4: Tạo biến con trỏ tĩnh trong Singleton

Tạo một biến con trỏ tĩnh trong Singleton
Tạo một biến con trỏ tĩnh trong Singleton

Trong bước này, chúng tôi sẽ tạo

biến con trỏ tĩnh kiểu “EngineDebugSingleton *”. Đây sẽ là biến sẽ được sử dụng để cấp phát singleton của chúng ta vào bộ nhớ và sẽ trỏ đến nó trong toàn bộ thời gian singleton của chúng ta được cấp phát vào bộ nhớ.

Đây là tệp tiêu đề của chúng tôi sẽ trông như thế nào sau khi tạo biến này

Bước 5: Tạo một hàm phiên bản

Tạo một hàm phiên bản
Tạo một hàm phiên bản

Bây giờ chúng tôi muốn tạo một ví dụ

hàm số. Hàm sẽ cần phải là một hàm tĩnh và sẽ muốn trả về một tham chiếu đến lớp của chúng ta (“EngineDebugSingleton &”). Chúng tôi đã gọi hàm của chúng tôi là Instance (). Trong chính hàm, chúng ta sẽ muốn kiểm tra trước nếu ptrInstance == nullptr (có thể được rút gọn thành! PtrInstance), nếu nó là nullptr, điều này có nghĩa là singleton chưa được cấp phát và trong phạm vi của câu lệnh if, chúng ta sẽ muốn phân bổ bằng cách thực hiện ptrInstance = new EngineDebugSingleton (). Đây là nơi bạn thực sự cấp phát singleton vào bộ nhớ. Sau khi thoát khỏi phạm vi của câu lệnh if, chúng ta sẽ trả về những gì ptrInstance đang trỏ tới, được biểu thị bằng cú pháp “* ptrInstance”. Chúng ta sẽ sử dụng hàm này rất nhiều khi tạo các hàm công khai tĩnh, vì vậy chúng ta có thể kiểm tra xem liệu singleton đã được tạo và cấp phát vào bộ nhớ chưa. Về bản chất, chức năng này làm cho nó để bạn có thể chỉ có một phân bổ của lớp và không có nhiều hơn nữa.

Đây là lớp của chúng ta sẽ trông như thế nào bây giờ sau khi tạo hàm Instance (). Như bạn có thể thấy, tất cả những gì chúng tôi đã làm đều nằm trong phần riêng tư của lớp học, điều này sẽ thay đổi một chút trong vài bước tiếp theo.

Bước 6: Tạo các hàm công cộng tĩnh

Tạo các hàm công cộng tĩnh
Tạo các hàm công cộng tĩnh
Tạo các hàm công cộng tĩnh
Tạo các hàm công cộng tĩnh
Tạo các hàm công cộng tĩnh
Tạo các hàm công cộng tĩnh

Sau khi bạn đã thực hiện chức năng từ

bước 5, bạn có thể bắt đầu tạo các hàm công khai tĩnh. Mỗi chức năng công cộng nên có một chức năng riêng đi cùng với nó, tên của chức năng này không được giống nhau. Tại sao làm cho hàm Static? Chúng tôi đang đặt các hàm công khai ở trạng thái tĩnh để chúng có thể được truy cập mà không cần đối tượng thực tế. Vì vậy, thay vì làm một cái gì đó như “EngineDebugSingleObj-> SomeFunction ()”, chúng tôi thực hiện “EngineDebugSingleton:: Some Function ()”. Điều này giúp cho một singleton có thể được truy cập về cơ bản ở bất kỳ đâu trong mã, miễn là bạn đã # bao gồm tệp tiêu đề trong tệp dự án cụ thể mà bạn đang làm việc. Với điều này, bạn cũng có thể tạo singleton thông qua bất kỳ chức năng công khai nào của nó.

Với mục đích của chúng tôi trong bước này, chúng tôi đã tạo hai hàm void tĩnh công khai, “add ()” và “subtract ()”. Trong phần riêng tư, chúng ta có thêm hai hàm, “PrivAdd ()” và “PrivSubtract ()”. Chúng tôi cũng đã thêm một biến int có tên là “NumberOfThings”. Định nghĩa cho các hàm này sẽ được đưa vào tệp CPP của các lớp của chúng tôi. Để dễ dàng đưa hàm vào tệp CPP, bạn đánh dấu, bằng con trỏ của bạn, hàm sẽ có một dòng màu xanh lá cây bên dưới và nhấn “Left ALT + ENTER”, nó sẽ cung cấp cho bạn tùy chọn tạo định nghĩa trong tệp CPP được liên kết của các lớp. Xem Ảnh 6.1 để biết tệp tiêu đề trông như thế nào và sau khi bạn đã tạo tất cả các định nghĩa hàm, CPP của bạn sẽ trông giống như Ảnh 6.2 ngoại trừ việc các định nghĩa hàm của bạn sẽ không có mã trong đó.

Bây giờ bạn sẽ muốn thêm mã tương tự như trong Ảnh 6.2 vào định nghĩa hàm của mình. Như đã nêu trước đó, các hàm public của chúng ta sẽ sử dụng hàm Instance (), hàm này sẽ trả về những gì ptrInstance đang trỏ tới. Điều này cho phép chúng tôi truy cập các chức năng riêng tư của lớp chúng tôi. Với bất kỳ hàm public nào của singleton, bạn chỉ nên gọi hàm Instance đó. Ngoại lệ duy nhất cho điều này là chức năng Chấm dứt của chúng tôi.

Lưu ý: Các hàm công khai và riêng tư chính xác được hiển thị trong bước này là không cần thiết, bạn có thể có các tên hàm và hoạt động khác nhau trong hàm riêng tư, nhưng đối với bất kỳ loại hàm công khai nào, bạn nên có một hàm riêng đi cùng với nó và trong trường hợp của chúng ta, hàm public nên luôn sử dụng hàm Instance ().

Bước 7: Tạo chức năng chấm dứt

Tạo chức năng chấm dứt
Tạo chức năng chấm dứt
Tạo chức năng chấm dứt
Tạo chức năng chấm dứt

Vì chúng ta chỉ có thể phân bổ singleton của chúng ta từ bộ nhớ trong lớp của chúng ta, chúng ta phải tạo một hàm công cộng tĩnh. Hàm này sẽ gọi hàm delete trên ptrInstance, hàm này gọi hàm hủy của lớp và sau đó chúng ta sẽ muốn đặt ptrInstance trở lại nullptr để nó có thể được cấp phát lại nếu chương trình của bạn không kết thúc. Bạn cũng sẽ muốn kết thúc các Singleton của mình để dọn dẹp bất kỳ bộ nhớ được cấp phát nào mà bạn đã cấp phát trong bất kỳ biến riêng tư nào của Singleton.

Bước 8: Đặt PtrInstance thành Nullptr

Đặt PtrInstance thành Nullptr
Đặt PtrInstance thành Nullptr

Để hoàn thành singleton của bạn, bạn muốn chuyển đến tệp EngineDebugSingleton. CPP và ở đầu tệp CPP, trong trường hợp của chúng tôi, hãy nhập “EngineDebugSingleton * EngineDebugSingleton:: ptrInstance = nullptr.”

Làm điều này ban đầu sẽ đặt ptrInstance thành nullptr, vì vậy khi bạn thực hiện lần đầu tiên hàm instance lần đầu tiên, lớp của chúng ta sẽ được phép cấp phát vào bộ nhớ. Nếu không có nó, rất có thể bạn sẽ gặp lỗi vì bạn đang cố truy cập vào bộ nhớ không được cấp phát gì cho nó.

Bước 9: Kiểm tra và kết luận

Kiểm tra và Kết luận
Kiểm tra và Kết luận

Bây giờ chúng tôi sẽ muốn kiểm tra xem singleton của chúng tôi để đảm bảo nó hoạt động, điều này sẽ liên quan đến việc chúng tôi gọi các chức năng công khai như được mô tả trong bước 6 và chúng tôi khuyên bạn nên thiết lập các điểm ngắt để xem qua mã của bạn và thấy rằng singleton đang hoạt động như nó nên được. Điểm bắt đầu của chúng tôi sẽ nằm trong main.cpp của dự án và main.cpp của chúng tôi bây giờ trông giống như hình ảnh bên dưới.

Xin chúc mừng! Bạn vừa hoàn thành việc triển khai Mẫu thiết kế Singleton đầu tiên của mình. Với mẫu thiết kế này, giờ đây bạn có thể sắp xếp hợp lý mã của mình theo nhiều cách khác nhau. Ví dụ: giờ đây, bạn có thể tạo hệ thống người quản lý hoạt động trong suốt thời gian chạy chương trình của mình, có thể được truy cập thông qua các chức năng tĩnh ở bất kỳ đâu mà bạn đã bao gồm lớp học.

Tệp tiêu đề cuối cùng của bạn sẽ giống như ảnh 7.1. Tệp CPP liên kết của singleton của bạn sẽ trông giống như Ảnh 6.2 với việc bổ sung mã được hiển thị ở bước 8. Hướng dẫn này cung cấp cho bạn cấu trúc đơn giản của Mẫu thiết kế Singleton.

Lời khuyên khắc phục sự cố:

Nhận lỗi liên quan đến bộ nhớ?

Đảm bảo bạn tham khảo bước 7 và bước 8 để đảm bảo rằng bạn đang đặt ptrInstance thành nullptr.

Xảy ra vòng lặp vô hạn?

Đảm bảo rằng đối với các hàm public, trong định nghĩa của chúng, bạn đang gọi hàm private, không phải hàm public giống nhau.

Các đối tượng được phân bổ trong singleton gây rò rỉ bộ nhớ?

Đảm bảo rằng bạn gọi hàm kết thúc của singleton khi thích hợp trong mã chương trình của bạn và trong trình hủy của singleton, hãy đảm bảo bạn bỏ cấp phát bất kỳ đối tượng nào đã được cấp phát cho bộ nhớ trong phạm vi của mã singleton.