写好的代码就是为了以后少写一些代码。
享元模式是在大量实例对象存在的情况下会占用大量的内存,所以呢,就想办法把这大量对象的公共部分提取出来,然后把不同的部分提取出来。这样的话,遇到公共部分的时候只要取一个内容就可以了,这样就节省了大量的内存。但是呢,这会带来一个问题:假如公共部分老是变化的话,这个模式就不合适了。
举个简单的例子:关系数据库存储数据的时候经常会把通用的信息给做成一个表。比方:每个学生的个人信息做成一个表,每个学生每学期的课程做成一个表,全体学生对应的各门课程的成绩就是整个数据表。全体学生的成绩表不会在成绩单中附加个人信息,要是全部附带个人信息的话就会产生很多的冗余信息,属于吃饱了撑的。关系数据库就是采用享元模式的原理来处理,所以节省了大量的空间。
下面的例子显示了享元模式的用法:
大学生基本信息就是学号+各种学籍信息。但是大学生分普通大学生和国防大学生。普通大学生的信息是身份证号,国防大学生的信息是军人证号。在打印信息的时候,学号+课程+成绩是一个表,个人信息是一个表。两个表组合起来就是一张完整的表格。
#pragma once
#include <string>
using namespace std;
class 学生基本信息
{
public:
学生基本信息();
~学生基本信息();
virtual void 基础信息() = 0;
virtual void 设置学号(string 学号, string 姓名) = 0;
virtual string 获取学号() = 0;
protected:
string 学号;
string 姓名;
};
#pragma once
#include "学生基本信息.h"
#include <iostream>
using namespace std;
class 国防全日制大学生 :
public 学生基本信息
{
public:
国防全日制大学生();
~国防全日制大学生();
void 基础信息()
{
cout << "学号: " << 学号 << ", 姓名: " << 姓名 << ", 军人编号: " << 军人编号 << ".";
}
void 设置学号(string 学号, string 姓名)
{
this->学号 = 学号;
this->姓名 = 姓名;
}
string 获取学号()
{
return this->学号;
}
void 设置军人编号(string 军人编号)
{
this->军人编号 = 军人编号;
}
private:
string 军人编号;
};
#pragma once
#include "学生基本信息.h"
#include <iostream>
using namespace std;
class 普通全日制大学生 :
public 学生基本信息
{
public:
普通全日制大学生();
~普通全日制大学生();
void 基础信息()
{
cout << "学号: " << 学号 << ", 姓名: " << 姓名 << ", 身份证号: " << 身份证号 << ".";
}
void 设置学号(string 学号, string 姓名)
{
this->学号 = 学号;
this->姓名 = 姓名;
}
string 获取学号()
{
return this->学号;
}
void 设置身份证(string 身份证号)
{
this->身份证号 = 身份证号;
}
private:
string 身份证号;
};
#pragma once
#include "学生基本信息.h"
#include "国防全日制大学生.h"
#include "普通全日制大学生.h"
#include <iostream>
#include <vector>
#include <string>
using namespace std;
class 学籍系统
{
public:
学籍系统();
~学籍系统();
void 信息录入(学生基本信息 *信息)
{
vecStudent.push_back(信息);
}
学生基本信息 *根据学号获取学生信息(string 学号)
{
for (vector<学生基本信息 *>::iterator it = vecStudent.begin(); it != vecStudent.end(); it++)
{
if ((*it)->获取学号().compare(学号) == 0)
{
return (*it);
}
}
return nullptr;
}
void 成绩打印(string 学号, string 学科, int 成绩)
{
学生基本信息 *学生 = 根据学号获取学生信息(学号);
if (学生 == nullptr)
{
cout << "查无此人" << endl;
return;
}
学生->基础信息();
cout << 学科 << "成绩为: " << 成绩 << endl;
}
private:
vector<学生基本信息 *> vecStudent;
};
// 享元模式.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include <string>
#include <iostream>
using namespace std;
#include "学籍系统.h"
#include "国防全日制大学生.h"
#include "普通全日制大学生.h"
#include "学生基本信息.h"
int _tmain(int argc, _TCHAR* argv[])
{
国防全日制大学生 *张三 = new 国防全日制大学生();
张三->设置学号("0000100", "张三");
张三->设置军人编号("abcdefghijklmnopqr");
普通全日制大学生 *李四 = new 普通全日制大学生();
李四->设置学号("0000101", "李四");
李四->设置身份证("123456789012345678");
普通全日制大学生 *王五 = new 普通全日制大学生();
王五->设置学号("0000102", "王五");
王五->设置身份证("123456789012345679");
学籍系统 系统;
系统.信息录入(张三);
系统.信息录入(李四);
系统.信息录入(王五);
// 0000100学号的学生成绩打印
系统.成绩打印("0000100", "高等数学", 86);
系统.成绩打印("0000100", "线性代数", 89);
系统.成绩打印("0000100", "计算机组成原理", 97);
系统.成绩打印("0000100", "数据结构", 78);
系统.成绩打印("0000101", "现代文学", 98);
系统.成绩打印("0000101", "西方哲学", 76);
系统.成绩打印("0000101", "论文写作", 78);
系统.成绩打印("0000102", "计算机组成原理", 97);
系统.成绩打印("0000102", "数据结构", 78);
系统.成绩打印("0000102", "现代文学", 98);
系统.成绩打印("0000102", "西方哲学", 76);
cout << "成绩一共11条,但是学生信息就3条,大大节省了空间" << endl;
getchar();
return 0;
}