享元是一种结构型设计模式,它摒弃了在每个对象中保存所有数据的方式,通过共享多个对象所共有的相同状态,让你能在有限的内存容量中载入更多对象。
Flyweight.h:
#ifndef FLYWEIGHT_H_
#define FLYWEIGHT_H_
#include
// 享元类包含了树类型的部分状态, 这些成员变量保存的数值对于特定树而言是唯一的。
// 很多树木之间包含共同的名字、颜色和纹理, 如果在每棵树中都存储这些数据就会浪费大量内存。
// 因此我们将这些「内在状态」导出到一个单独的对象中, 然后让众多的单个树对象去引用它。
class TreeType {
public:
TreeType(std::string n, std::string c, std::string t) :
name_(n), color_(c), texture_(t) {}
void draw(std::string canvas, double x, double y) {
// 1. 创建特定类型、颜色和纹理的位图
// 2. 在画布坐标(x,y)处绘制位图
return;
}
private:
std::string name_;
std::string color_;
std::string texture_;
};
#endif // FLYWEIGHT_H_
Context.h:
#ifndef CONTEXT_H_
#define CONTEXT_H_
#include
#include "Flyweight.h"
// 情景对象包含树类型的「外在状态」, 程序中可以创建数十亿个此类对象, 因为它们体积很小: 仅有两个浮点坐标类型和一个引用成员变量
class Tree {
public:
Tree(double x, double y, TreeType* t) : x_(x), y_(y), type_(t) {}
void draw(std::string canvas) {
return type_->draw(canvas, x_, y_);
}
private:
double x_;
double y_;
TreeType* type_;
};
#endif // CONTEXT_H_
FlyweightFactory.h
#ifndef FLYWEIGHT_FACTORY_H_
#define FLYWEIGHT_FACTORY_H_
#include
#include
#include
#include "Flyweight.h"
// 享元工厂: 决定是否复用已有享元或者创建一个新的对象, 同时它也是一个单例模式
class TreeFactory {
public:
static TreeFactory* getInstance() {
if (instance_ == nullptr) {
mutex_.lock();
if (instance_ == nullptr) {
instance_ = new TreeFactory();
}
mutex_.unlock();
}
return instance_;
}
TreeType* getTreeType(std::string name, std::string color, std::string texture) {
std::string key = name + "_" + color + "_" + texture;
auto iter = tree_types_.find(key);
if (iter == tree_types_.end()) {
// 新的tree type
TreeType* new_tree_type = new TreeType(name, color, texture);
tree_types_[key] = new_tree_type;
return new_tree_type;
} else {
// 已存在的tree type
return iter->second;
}
}
private:
TreeFactory() {}
static TreeFactory* instance_;
static std::mutex mutex_;
// 共享池, 其中key格式为name_color_texture
std::map<std::string, TreeType*> tree_types_;
};
#endif // FLYWEIGHT_FACTORY_H_
FlyweightFactory.cpp
#include "FlyweightFactory.h"
TreeFactory* TreeFactory::instance_ = nullptr;
std::mutex TreeFactory::mutex_;
Client.h:
#ifndef CLIENT_H_
#define CLIENT_H_
#include
#include
#include
#include "FlyweightFactory.h"
#include "Context.h"
// Forest包含数量及其庞大的Tree
class Forest {
public:
void planTree(double x, double y, std::string name, std::string color, std::string texture) {
TreeType* type = TreeFactory::getInstance()->getTreeType(name, color, texture);
Tree tree = Tree(x, y, type);
trees_.push_back(tree);
}
void draw() {
for (auto tree : trees_) {
tree.draw("canvas");
}
}
private:
std::vector<Tree> trees_;
};
#endif // CLIENT_H_
main.cpp
#include "Client.h"
int main() {
system("chcp 65001");
Forest* forest = new Forest();
// 在forest中种植很多棵树
for (int i = 0; i < 500; i++) {
for (int j = 0; j < 500; j++) {
double x = i;
double y = j;
// 树类型1: 红色的杉树
forest->planTree(x, y, "杉树", "红色", "");
// 树类型2: 绿色的榕树
forest->planTree(x, y, "榕树", "绿色", "");
// 树类型3: 白色的桦树
forest->planTree(x, y, "桦树", "白色", "");
}
}
forest->draw();
system("pause");
delete forest;
}