一个图书管理系统中使用访问者模式(Visitor Pattern)来统计所有馆藏文献总页数的类图和部分C++代码实现

一个图书管理系统中使用访问者模式(Visitor Pattern)来统计所有馆藏文献总页数的类图和部分C++代码实现。

类图解释

  1. Library(图书馆):这是管理图书和论文的类,它包含一个LibraryVisitor类型的成员变量,用于访问者模式。
  2. LibraryVisitor(访问者):这是一个抽象类,定义了访问者的基本接口。
  3. LibraryItemInterface(图书馆项接口):这是一个接口,定义了所有图书馆项(如图书和论文)必须实现的方法,以便访问者可以访问它们。
  4. LibrarySumPrintVisitor(求和打印访问者):这是一个具体的访问者类,实现了LibraryVisitor接口,用于计算和打印所有文献的总页数。
  5. Book(图书)Article(论文):这两个类都实现了LibraryItemInterface接口,表示图书馆中的不同类型的文献。

C++代码解释

  1. LibraryVisitor类:这是一个抽象类,定义了一个纯虚函数accept,用于接受访问者。
  2. LibraryItemInterface类:这是一个接口类,定义了两个纯虚函数getNumberacceptgetNumber用于获取文献的页数,accept用于接受访问者。
  3. Article类:实现了LibraryItemInterface接口,包含论文的标题、作者、起始页和结束页。getNumber函数计算论文的页数,accept函数接受一个访问者对象。
  4. Book类:同样实现了LibraryItemInterface接口,包含图书的标题、作者和页数。getNumber函数直接返回图书的页数,accept函数接受一个访问者对象。

这个设计模式允许在不修改现有类的情况下,增加新的操作(如计算总页数),通过访问者类来实现这些操作。

在提供的图片中,图书馆项接口(LibraryItemInterface)定义了两个方法,这些方法是所有实现了该接口的类(如图书Book和论文Article)必须提供的。具体方法如下:

  1. getNumber():这个方法应该返回一个整数值,表示该图书馆项的页数。对于图书来说,这可能直接返回其页数;对于论文来说,这可能需要计算起始页和结束页之间的页数差再加1(因为包括起始页和结束页)。

  2. accept(LibraryVisitor* visitor):这个方法接受一个LibraryVisitor类型的指针作为参数。这是访问者模式的核心,它允许不同的访问者对象来访问并操作实现了LibraryItemInterface的类。通过这种方式,可以在不修改图书和论文类的情况下,增加新的操作,如计算总页数。

这两个方法使得LibraryItemInterface成为一个定义了如何被访问者访问的协议,而具体的实现则由BookArticle类来完成。这样的设计使得系统更加灵活,易于扩展。

1. 代码补全(推测题目可能是补全缺失部分)

LibraryItemInterface类中,由于要实现Visitor模式,通常需要一个接受访问者的纯虚函数accept 。所以(1)处应补充:

virtual void accept(LibraryVisitor* visitor) = 0;

解释:在Visitor模式中,被访问的元素(这里是LibraryItemInterface及其子类ArticleBook )需要有一个方法来接受访问者对象。将accept函数定义为纯虚函数,是为了强制其子类(ArticleBook )去实现该函数,这样访问者才能正确地访问不同类型的元素。

2. 完整代码实现思路

  • Article类的accept函数实现
Article::Article(string p_author, string p_title, int p_start_page, int p_end_page) 
    : m_author(p_author), m_title(p_title), m_start_page(p_start_page), m_end_page(p_end_page) {}
int Article::getNumberOfPages() {
    return m_end_page - m_start_page + 1;
}
void Article::accept(LibraryVisitor* visitor) {
    visitor->visitArticle(this);
}

解释:Article类的构造函数用于初始化论文的作者、标题、起始页码和结束页码。getNumberOfPages函数用于计算论文的页数。accept函数调用访问者的visitArticle方法,并将自身(this指针)传递过去,以便访问者对该论文对象进行操作。

  • Book类相关函数实现(假设类似Article ,补充缺失部分)
Book::Book(string p_author, string p_title, int p_pages) 
    : m_author(p_author), m_title(p_title), m_pages(p_pages) {}
int Book::getNumberOfPages() {
    return m_pages;
}
void Book::accept(LibraryVisitor* visitor) {
    visitor->visitBook(this);
}

解释:Book类的构造函数初始化书的作者、标题和页数。getNumberOfPages直接返回书的总页数。accept函数调用访问者的visitBook方法,并传递自身指针,让访问者对书对象进行处理。

  • LibraryVisitor类及具体访问者类(如LibrarySumPrintVisitor
class LibraryVisitor {
public:
    virtual void visitArticle(Article* article) = 0;
    virtual void visitBook(Book* book) = 0;
};
class LibrarySumPrintVisitor : public LibraryVisitor {
private:
    int totalPages;
public:
    LibrarySumPrintVisitor() : totalPages(0) {}
    void visitArticle(Article* article) override {
        totalPages += article->getNumberOfPages();
    }
    void visitBook(Book* book) override {
        totalPages += book->getNumberOfPages();
    }
    int getTotalPages() {
        return totalPages;
    }
};

解释:LibraryVisitor是抽象访问者类,定义了访问不同类型文献(论文和书)的纯虚方法。LibrarySumPrintVisitor是具体的访问者类,用于统计总页数。它继承自LibraryVisitor ,实现了visitArticlevisitBook方法,在方法中累加对应文献的页数,并且提供了getTotalPages方法获取统计的总页数。

  • 测试代码示例
int main() {
    Article article("Author1", "ArticleTitle", 1, 25);
    Book book("Author2", "BookTitle", 540);
    LibrarySumPrintVisitor visitor;
    article.accept(&visitor);
    book.accept(&visitor);
    std::cout << "Total number of pages: " << visitor.getTotalPages() << std::endl;
    return 0;
}

解释:在main函数中,创建了一篇论文和一本书的对象,然后创建统计总页数的访问者对象。通过调用accept方法让访问者访问论文和书对象,最后输出统计得到的总页数。
下面是一个图书管理系统中使用访问者模式统计所有馆藏文献总页数的类图和C++代码实现:

类图结构

+---------------------+       +---------------------+       +---------------------+
|     Visitor         |       |     Element         |       |    ConcreteElement  |
+---------------------+       +---------------------+       +---------------------+
| + visit(Book*)      |       | + accept(Visitor*)  |<------| + accept(Visitor*)  |
| + visit(Magazine*)  |       +---------------------+       | + getPageCount()    |
| + visit(Journal*)   |               ^                     +---------------------+
+---------------------+               |                           /_\
         ^                           |                            |
         |                           |                            |
         |          +-------------------------------+             |
         +----------|    ConcreteVisitor (Counter)  |             |
                    +-------------------------------+             |
                    | - totalPages                  |             |
                    | + visit(Book*)                |             |
                    | + visit(Magazine*)            |             |
                    | + visit(Journal*)             |             |
                    | + getTotalPages()             |             |
                    +-------------------------------+             |
                                                                +---------------------+
                                                                |      Book           |
                                                                +---------------------+
                                                                | - title             |
                                                                | - pages             |
                                                                +---------------------+
                                                                
                                                                +---------------------+
                                                                |     Magazine        |
                                                                +---------------------+
                                                                | - issueNumber       |
                                                                | - pages             |
                                                                +---------------------+
                                                                
                                                                +---------------------+
                                                                |      Journal        |
                                                                +---------------------+
                                                                | - volume            |
                                                                | - pages             |
                                                                +---------------------+

C++代码实现

#include <iostream>
#include <vector>
#include <string>

// 前置声明
class Book;
class Magazine;
class Journal;

// 访问者接口
class Visitor {
public:
    virtual void visit(Book* book) = 0;
    virtual void visit(Magazine* magazine) = 0;
    virtual void visit(Journal* journal) = 0;
    virtual ~Visitor() = default;
};

// 元素接口
class LibraryItem {
public:
    virtual void accept(Visitor* visitor) = 0;
    virtual int getPageCount() const = 0;
    virtual ~LibraryItem() = default;
};

// 具体元素:书
class Book : public LibraryItem {
private:
    std::string title;
    int pages;

public:
    Book(const std::string& title, int pages) : title(title), pages(pages) {}

    void accept(Visitor* visitor) override {
        visitor->visit(this);
    }

    int getPageCount() const override {
        return pages;
    }

    std::string getTitle() const {
        return title;
    }
};

// 具体元素:杂志
class Magazine : public LibraryItem {
private:
    int issueNumber;
    int pages;

public:
    Magazine(int issueNumber, int pages) : issueNumber(issueNumber), pages(pages) {}

    void accept(Visitor* visitor) override {
        visitor->visit(this);
    }

    int getPageCount() const override {
        return pages;
    }

    int getIssueNumber() const {
        return issueNumber;
    }
};

// 具体元素:期刊
class Journal : public LibraryItem {
private:
    int volume;
    int pages;

public:
    Journal(int volume, int pages) : volume(volume), pages(pages) {}

    void accept(Visitor* visitor) override {
        visitor->visit(this);
    }

    int getPageCount() const override {
        return pages;
    }

    int getVolume() const {
        return volume;
    }
};

// 具体访问者:页数计数器
class PageCounter : public Visitor {
private:
    int totalPages;

public:
    PageCounter() : totalPages(0) {}

    void visit(Book* book) override {
        totalPages += book->getPageCount();
    }

    void visit(Magazine* magazine) override {
        totalPages += magazine->getPageCount();
    }

    void visit(Journal* journal) override {
        totalPages += journal->getPageCount();
    }

    int getTotalPages() const {
        return totalPages;
    }
};

// 图书馆类管理馆藏
class Library {
private:
    std::vector<LibraryItem*> items;

public:
    void addItem(LibraryItem* item) {
        items.push_back(item);
    }

    int calculateTotalPages() {
        PageCounter counter;
        for (auto item : items) {
            item->accept(&counter);
        }
        return counter.getTotalPages();
    }

    ~Library() {
        for (auto item : items) {
            delete item;
        }
    }
};

// 使用示例
int main() {
    Library library;
    
    library.addItem(new Book("C++ Primer", 976));
    library.addItem(new Magazine(123, 84));
    library.addItem(new Journal(5, 128));
    library.addItem(new Book("Design Patterns", 384));
    
    std::cout << "馆藏文献总页数: " << library.calculateTotalPages() << std::endl;
    
    return 0;
}

代码说明

  1. Visitor接口:定义了访问不同类型文献的方法
  2. Element接口:所有文献类型必须实现的接口,包含accept方法
  3. ConcreteElements:具体的文献类型(Book、Magazine、Journal)
  4. ConcreteVisitor:实现了Visitor接口的具体访问者,负责统计总页数
  5. Library类:管理馆藏文献,并提供计算总页数的方法

访问者模式的优势

  • 符合开闭原则:新增文献类型无需修改现有代码
  • 集中统计逻辑:所有统计代码集中在Visitor实现中
  • 易于扩展:可以添加新的Visitor实现来执行不同的统计任务
  • 在提供的代码片段中,getNumber() 方法的具体实现没有直接展示,但是可以根据类的设计和方法的预期功能来推断其实现方式。

对于 Article

对于论文(Article),getNumber() 方法需要计算论文的总页数。论文的页数可以通过结束页码减去起始页码然后加1来计算(因为包括起始页和结束页)。假设 m_start_pagem_end_page 分别是论文的起始页和结束页,getNumber() 方法的实现可能如下:

int Article::getNumber() {
    return m_end_page - m_start_page + 1;
}

对于 Book

对于图书(Book),如果图书的页数直接存储在一个成员变量中(如 m_pages),那么 getNumber() 方法可能直接返回这个值。假设 m_pages 是存储图书页数的成员变量,getNumber() 方法的实现可能如下:

int Book::getNumber() {
    return m_pages;
}

这两个实现都符合 LibraryItemInterface 接口的要求,即每个实现了该接口的类都需要提供一个 getNumber() 方法来返回其页数。这样的设计允许访问者(如 LibrarySumPrintVisitor)通过调用 getNumber() 方法来获取每种类型的图书馆项的页数,进而进行进一步的处理,如计算总页数。
在这里插入图片描述

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Bol5261

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值