flyweight pattern

实例的属性可分为两种:

  • 内在状态intrinsic state:可以被共享的状态
  • 外在状态extrinsic state:不可被共享的状态,经常被外部实例更改

享元模式的本质是,抽取公共属性作为单独的类,以静态形式存储。每个实例都拥有这个公共属性的指针。也即“共享”一部分“元数据”。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
class TreeType {
std::string name_;
std::string color_;
std::string texture_;
public:
TreeType(std::string name, std::string color, Texture texture): name_(name), color_(color), texture_(texture) {}
void draw(const Canvas& c, int x, int y) {
// draw with the intrinsic color & texture + extrinsic xy coord
}
}

class TreeFactory {
public:
static std::unordered_map<std::string, std::shared_ptr<TreeType>> treeTypes_;
std::shared_ptr<TreeType> getTreeType(const std::string name, static const std::string color, const std::string texture) {
auto it = treeTypes_.find(name);
if (it != treeTypes_.end()) return it->second;
auto t = std::make_shared<TreeType>(name, color, texture);
treeTypes_[name] = t;
return t;
}
}

std::unordered_map<std::string, std::shared_ptr<TreeType>> TreeFactory::treeTypes_;

class Tree {
int x_;
int y_;
std::shared_ptr<TreeType> type_; // 享元模式的核心。type_在相同种类的树之间是共享的。此处必须使用指针,而不是实例!否则存储的将是副本,而不是共享对象。
public:
Tree(int x, int y, std::shared_ptr<TreeType> type): x_(x), y_(y), type_(type) {}
void draw(const Canvas& c) {
type_->draw(c, x_, y_);
}
}

class Forest {
std::vector<Tree> trees_;
void plantTree(int x, int y, std::string name, std::string color, std::string texture) {
auto type = TreeFactory::getTreeType(name, color, texture);
Tree tree = Tree(x, y, type);
trees_.push_back(tree);
}
void draw(const Canvas& c) {
for (int i = 0; i < trees_.size(); i++) trees_[i].draw(c);
}
}