Hello
I am doing a beginner C++ project and its simply a Library Mangement System where a student will hire, give back a book, book and hire records are stored in a binary file etc.
I'm approaching the project as though the project would be used by other developers and that I need to design the classes so they cannot be incorrectly used, the project can be scaled/extended at a later date easily and avoid gotchas/bugs down the track so I am being very strict (overkill almost) with my implementation.
Therefore, I have some features of the LibraryBook class that I want to implement but dont quite know if this is the best way of doing. If you could provide advice below it would be much appreciated.
Classes:
- LibraryManagementSystem (LMS)
- LibraryBook
- Student
LibraryBook features I want to implement:
- The class has the expected private properties of title, author, availability, id. I have made the LMS a friend class so that it and only it can change the books availability, maybe even author, title (for scalability/extendability). Would you use friend here or maybe another technique?
- A book object should only ever be created by the LMS, this makes sense I guess because a Student shouldn't be able to make a new book only the LMS. So I was thinking of making the LibraryBook class private but that means a Student wont even be able to hold a book (as a property in their class). I am thinking I should only ever give a handle of the book to the Student? Maybe this is the case for the application of the factory design pattern.
- A LibraryBook must have its title, author, etc. defined always. So I have made the constructor explicit. Should I make the default constructor private? That way a book can only ever be created with defined title, author, etc.
LMS features I want to implement:
- I want to store the LibraryBooks in a std::map <string, std::shared_ptr<LibraryBook>>. This is because a student will most likely ask/search for the book by title (title string = key), the LibraryBook dynamic memory will be automatically deleted and I can give the Student a weak_ptr to the LibraryBook which means they cant change anything on that object.
Knowing what I want to achieve above; can you provide advice on design patterns and etc. I should use and any errors I have made in my implementation below?
class Student
{
public:
// I dont think that hire book should be a student method but a LMS method because the LMS issues a book, creates a record etc.
weak_ptr<LibraryBook> curBook; // is this ok as public? or should only the LMS be able to set a students book? Maybe this property only should be friend with LMS?
protected:
private:
const string firstName;
const string lastName;
const unsigned int ID;
};
class LibraryBook
{
public:
friend class LibraryManagementSystem;
protected:
private:
explicit LibraryBook(string nTitle, string nAuthor) : title(nTitle), author(nAuthor) { } // will this mean noone not even LMS can create a book using the default constructor? They have to use this one only?
LibraryBook();
// No need to implement destructor because implicitly created and theres no dyn memory in this class
LibraryBook(const LibraryBook& lB); // dont implement to disallow copying a book
void operator=(const LibraryBook& lB); // dont implement to disallow copying a book
const string title;
const string author;
const unsigned int ID;
};
class LibraryManagementSystem
{
public:
static LibraryManagementSystem& Instance()
{
static LibraryManagementSystem instance;
return instance;
}
weak_ptr<LibraryBook> hireBook(string bookTitle, Student& student)
{
weak_ptr<LibraryBook> book; // initialised as null ptr I think?
if (libraryBooks.find(bookTitle) == libraryBooks.end())
// what should I return? An empty/null weak_ptr?
book = libraryBooks[bookTitle]; // is this cast allowed/possible? Is it allowed to write/overwrite a weak ptr?
student.curBook = book;
// TODO: create LMS record of who has book, when due back, etc.
return book;
}
protected:
private:
LibraryManagementSystem() {}
~LibraryManagementSystem() {}
LibraryManagementSystem(const LibraryManagementSystem& lms); // dont implement to disallow copy constructor
void operator=(const LibraryManagementSystem& lms); // dont implement assignment operator
map<string, shared_ptr<LibraryBook>> libraryBooks;
};