C++:单例模式例题解析

来源:互联网 发布:两个矩阵相乘怎么算 编辑:程序博客网 时间:2024/04/29 17:11

C++:单例模式例题解析

标签:单例模式 队列

by 小威威


这篇博文主要是讲解例题,如要深入了解单例模式,可以参考这篇文章:C++设计模式——单例模式,我个人觉得写得不错。

单例模式是C++设计模式中的一种,它保证一个类只有一个实例,并提供一个访问它的全局访问点。因为类对象的生成是通过构造函数实现的,为了保证不被随便调用并保存唯一实例,应将构造函数放到private标签内。单例模式还需要提供一个访问它的全局访问点,不难想到要在类中定义一个静态指针来指向唯一实例。

下面就上例题:(Author: 黎洋)
In this assignment, you are required to finish two classes’ definition according to their declaration respectly.
1. Two basic concepts are needed before you begin to code: 1. Singleton, 2. linked Queue.

SINGLETON: Singleton is a kind of frequently-used Design Pattern(but often be prone to misuse).
Ensure a class only has one instance, and provide a global point of access to it.
Use the Singleton pattern when
● there must be exactly one instance of a class, and it must be accessible to clients from a wellknown access point.
● when the sole instance should be extensible by subclassing, and clients should be able to use an extended instance without modifying their code.

2. Class Job has:
(1)one static variable “number”, which indicates current object’s id. you shold increment it when you create an new object. Attention: when the object was destoyed, this variable do not subtract by 1;
(2)three memeber variables:

id means this object’s id. you need to set the current number to id when create an object.

priority, means the importance among all jobs.

nextJob, a Job pointer, which points to the next Job.
(3)function toString return a string, its format is like: [id:priority], for example: [0:234]..

3. Class JobManager only has one instance, JobManager can manage the jobs in the job queue.
JobManager manages the job queue according to the principle FIFO(First In, First Out), no matter what the priority is..
This Class has a member variable named “jobFrontPointer”( Job *), which points to the first Job in the queue(first add).
static variable instance is the only instance of this class. You need to implement two static function getInstance and deleteInstance. “getInstance” will return the only instance of this class; “deleteInstance” will delete the only instance, if delete successfully, return true; otherwise, return false.
6 member functions:
void addJob(int pri = 0); which adds one job(its priority is pri, default: 0) to the end of queue.
void finishOneJob(); which finish the job in the begin and pop it out of the queue.
void sortJob(); which sorts the current queue according to their priority (if same, then the smaller id is in front of the larger one).
void printJob(); print the queue’s job, like “[2:23432]->[3:1]->[4:5]->[5:0]->[6:6666]” with endl.
int getNumOfJob(); return the number of jobs in the queue.
void clear(); clear the queue.

这道题主要是要求实现Job.cpp、JobManager.cpp,main.cpp、Job.h, JobManager.h已经给出。

// main.cpp#include "JobManager.h"using namespace std;int main() {    JobManager *manager1 = JobManager::getInstance();    JobManager *manager2 = JobManager::getInstance();    int pris[5] = {234, 23, 23432, 1, 5};    for (int i = 0; i < 5; i++) {        manager1->addJob(pris[i]);    }    manager2->printJob();    cout << "The number of job is: " << manager1->getNumOfJob() << endl;    manager1->finishOneJob();    cout << "The number of job is: " << manager1->getNumOfJob() << endl;    manager2->finishOneJob();    cout << "The number of job is: " << manager1->getNumOfJob() << endl;    manager1->addJob();    manager1->addJob(6666);    manager1->printJob();    cout << "The number of job is: " << manager1->getNumOfJob() << endl;    manager2->clear();    manager1->printJob();    cout << "The number of job is: " << manager1->getNumOfJob() << endl;    int jobNum, jobPriority, deleteNum;    cin >> jobNum;    for (int i = 0; i < jobNum; i++) {        cin >> jobPriority;        manager2->addJob(jobPriority);    }    manager1->sortJob();    manager2->printJob();    cin >> deleteNum;    while (deleteNum--) {        manager1->finishOneJob();    }    manager1->printJob();    cout << "The number of job is: " << manager2->getNumOfJob() << endl;    if (JobManager::deleteInstance()) cout << "Delete successfully!\n";    else cout << "Delete failure!\n";    if (JobManager::deleteInstance()) cout << "Delete successfully!\n";    else cout << "Delete failure!\n";} // Job.h* * declaration for class Job.. */#ifndef JOB_H#include<string>using namespace std;class Job {    public:        explicit Job(int priority = 0);        void setId(int id);        int getId() const;        void setPriority(int priority);        int getPriority() const;        void setNext(Job *job);        Job *getNext() const;        string toString();    private:        static int number;        int id;        int priority;        Job *nextJob;};#endif// JobManager.h#ifndef JOBMANAGER_H#define JOBMANAGER_H#include <iostream>#include "Job.h"// disallow copy constructor and assignment operator#define DISALLOW_COPY_AND_ASSIGN(TypeName) \  TypeName(const TypeName&);               \  void operator=(const TypeName&)class JobManager {    public:        // get the unique instance        static JobManager* getInstance();        static bool deleteInstance();        void addJob(int priority = 0);        void finishOneJob();        void sortJob();        void printJob();        int getNumOfJob();        void clear();    private:        Job * jobFrontPointer;        ~JobManager();        JobManager();        static JobManager* instance;        DISALLOW_COPY_AND_ASSIGN(JobManager);};#endif

Job.cpp的实现不难,所以就简单略过了。

# include <string># include <sstream># include "Job.h"using std::string;using std::stringstream;int Job :: number = 0;Job :: Job(int priority) : id(number++),            priority(priority), nextJob(NULL) {}void Job :: setId(int id) { this->id = id; }int Job :: getId() const { return id; }void Job :: setPriority(int priority) { this->priority = priority; }int Job :: getPriority() const { return priority; }void Job :: setNext(Job *job) { nextJob = job; }string Job::toString() {    stringstream ss;    ss << "[" << id << ":" << priority << "]";    return ss.str();}

下面谈谈JobManager.cpp

getInstance() 函数是用来获取唯一实例。对指向唯一实例的全局指针进行判断,若为NULL,说明实例不存在,则用new给它分配一个实例,然后返回,如若不等于NULL,直接返回。

deleteInstance() 函数是用来删除唯一实例。对指向唯一实例的全局指针进行判断,若为NULL,说明实例不存在,不能执行删除操作,返回false,如若不等于NULL,就将其delete,同时不要忘记,要将这个全局指针置为NULL,然后返回true。

构造函数就是将全局指针置空,析构函数就是将动态内存释放。

由题意可知,要通过队列实现Job对象的存储,我是用链表实现队列的。

addJob() 函数是往队头增加一个对象。因为队列是FIFO,所以不难想到头结点应该是存储第一个放入的对象,接下来的结点依次存储后来放入的对象。首先要判断头指针是否为空,若为空,直接用该指针new一块内存;若不为空,就遍历到链表最后一个结点,然后用最后一个结点的next指针分配一块动态内存。遍历到最后一个结点的固定算法是:

    while (tempPointer->getNext() != NULL) {        tempPointer = tempPointer->getNext();    }

在使用这个之前,一定要保证tempPointer不为NULL。

finishOneJob() 其实就是实现链表第一个结点的删除,多次调用可实现整个链表的删除。

sortJob()函数有两种实现方法:
(1)第一种就是自己用代码实现;
(2)第二种就是调用std::sort函数。

由题意可知,priority越大,排的越前,如果一样大,则id小的排在前。

对于第一种方法,可以写一个冒泡排序,因为结点数固定,循环执行的次数就固定,因此可以先写两个冒泡固定的for循环确定循环次数。然后对相邻结点的数据进行判断,如若符合交换的条件,则交换数据。这种方法的好处就是不用实现交换结点,比较方便,不容易出错。

对于第二种方法,可以将链表的结点存储在数组中,然后调用std::sort进行排序,就不用自己实现代码了。这里可以定义一个结点指针数组,这样待会就可以直接利用这个新数组生成新链表。不过,要调用含三个形参的sort函数。现在讲解sort函数的用法。

根据cplusplus,sort的相关用法如下:

default (1) template <class RandomAccessIterator>  void sort (RandomAccessIterator first, RandomAccessIterator last);custom (2)  template <class RandomAccessIterator, class Compare>  void sort (RandomAccessIterator first, RandomAccessIterator last, Compare comp);

Sort elements in range
Sorts the elements in the range [first,last) into ascending order.

The elements are compared using operator< for the first version, and comp for the second.

Equivalent elements are not guaranteed to keep their original relative order (see stable_sort).

first, last
Random-access iterators to the initial and final positions of the sequence to be sorted. The range used is [first,last), which contains all the elements between first and last, including the element pointed by first but not the element pointed by last.
RandomAccessIterator shall point to a type for which swap is properly defined and which is both move-constructible and move-assignable.
comp
Binary function that accepts two elements in the range as arguments, and returns a value convertible to bool. The value returned indicates whether the element passed as first argument is considered to go before the second in the specific strict weak ordering it defines.
The function shall not modify any of its arguments.
This can either be a function pointer or a function object.

重点细节我已用黑体字标出。
1.带两个形参的sort()函数默认按升序排列;
2.first指数组第一个元素的地址,但last并不是指数组最后一个元素的地址,而是数组最后一个元素地址往后移一位。也就是说,相当于区间[first, last)。
3.comp指的是排序的要求。在带两个形参的sort()函数中,“<”就是它的排序要求,如今带三个形参的sort()函数用comp代替了这种要求。就如上文所写,其实comp的返回值决定了第一个参数是否应该排列在第二个参数之前。也就是说,如果comp返回true,说明第一个参数应该排列在第二个参数之前,如果comp返回false,说明第一个参数应该排列在第二个参数之后。
搞懂了sort函数的用法以后就能很容易地调用sort函数了。

printJob() 就是实现一个输出,很简单。

getNumOfJob()也很简单,用一个count对整个链表进行遍历统计。

clear()就是多次调用finishOneJob()函数。

完整代码如下:

# include <iostream># include "JobManager.h"using std::cout;using std::endl;JobManager* JobManager :: instance = NULL;JobManager* JobManager :: getInstance() {    if (instance == NULL) {        instance = new JobManager;    }    return instance;}bool JobManager :: deleteInstance() {    if (instance == NULL) return false;    if (instance != NULL) {        delete instance;        instance = NULL;        return true;    }}void JobManager :: addJob(int priority) {    if (jobFrontPointer == NULL) {        jobFrontPointer = new Job(priority);    } else {        Job *pArr = jobFrontPointer;        while (pArr->getNext() != NULL) {            pArr = pArr->getNext();        }        Job *pArr2 = new Job(priority);        pArr->setNext(pArr2);    }}void JobManager :: finishOneJob() {    if (jobFrontPointer != NULL) {        Job *pArr = jobFrontPointer->getNext();        delete jobFrontPointer;        jobFrontPointer = pArr;    }}/*void JobManager::sortJob() {    // if no or one item in queue, no need to sort it..    if (jobFrontPointer == NULL || jobFrontPointer->getNext() == NULL) return;    int nums = getNumOfJob(), i = 0;    Job *array[nums];    Job *flagPointer = jobFrontPointer;    // store each job in array..    while (flagPointer != NULL) {        array[i++] = flagPointer;        flagPointer = flagPointer->getNext();    }    // sort each job..    sort(array, array + nums, cmp);    array[nums - 1]->setNext(NULL);    jobFrontPointer = array[0];    flagPointer = jobFrontPointer;    for (i = 1; i < nums; i++) {        flagPointer->setNext(array[i]);        flagPointer = flagPointer->getNext();    }}*/void JobManager :: sortJob() {    if (jobFrontPointer == NULL) return;    Job *pArr = jobFrontPointer;    if (pArr->getNext() == NULL) return;    for (int i = 0; i < getNumOfJob()-1; i++) {        for (int j = 0; j < getNumOfJob()-1-i; j++) {            if (pArr->getPriority() < pArr->getNext()->getPriority()) {                int temp1 = pArr->getId();                int temp2 = pArr->getPriority();                pArr->setId(pArr->getNext()->getId());                pArr->getNext()->setId(temp1);                pArr->setPriority(pArr->getNext()->getPriority());                pArr->getNext()->setPriority(temp2);            }            if (pArr->getPriority() == pArr->getNext()->getPriority()) {                if (pArr->getId() > pArr->getNext()->getId()) {                    int temp1 = pArr->getId();                    int temp2 = pArr->getPriority();                    pArr->setId(pArr->getNext()->getId());                    pArr->getNext()->setId(temp1);                    pArr->setPriority(pArr->getNext()->getPriority());                    pArr->getNext()->setPriority(temp2);                }            }            pArr = pArr->getNext();        }        pArr = jobFrontPointer;    }}void JobManager :: printJob() {    if (jobFrontPointer == NULL) {        cout << "empty!" << endl;        return;    }    Job *pArr = jobFrontPointer;    while (pArr != NULL) {        cout << pArr->toString();        pArr = pArr->getNext();        if (pArr != NULL) {            cout << "->";        }    }    cout << endl;}int JobManager :: getNumOfJob() {    int count = 0;    Job *pArr = jobFrontPointer;    while (pArr != NULL) {        count++;        pArr = pArr->getNext();    }    return count;}/*void JobManager::clear() {    while (jobFrontPointer) {        finishOneJob();    }}*/void JobManager :: clear() {    Job *pArr = jobFrontPointer;    while (pArr != NULL) {        pArr = pArr->getNext();        jobFrontPointer->setNext(NULL);        delete jobFrontPointer;        jobFrontPointer = pArr;    }}JobManager :: ~JobManager() {    if (jobFrontPointer != NULL)        clear();}JobManager :: JobManager() : jobFrontPointer(NULL) {}JobManager :: JobManager(const JobManager& jobmanager) {    jobFrontPointer = jobmanager.jobFrontPointer;}void JobManager :: operator=(const JobManager& jobmanager) {    jobFrontPointer = jobmanager.jobFrontPointer;}

以上内容皆为本人观点,欢迎大家提出批评和指导,我们一起探讨!


0 0
原创粉丝点击