享元模式:运用共享技术有效地支持大量细粒度的对象。在有大量对象时,把其中共同的部分抽象出来,如果有相同的业务请求,直接返回内存中已有的对象,避免重新创建。
以下情况可以考虑使用享元模式:
- 系统中有大量的对象,这些对象消耗大量的内存,且这些对象的状态可以被外部化。
对于享元模式,需要将对象的信息分为两个部分:内部状态和外部状态。内部状态是指被共享出来的信息,储存在享元对象内部且不随环境变化而改变;外部状态是不可以共享的,它随环境改变而改变,是由客户端控制的。
1,运行结果
2,代码示例
#include <iostream>
#include <iomanip>
#include <vector>
#include <map>
#include <memory>
struct Point {
int x = 0;
int y = 0;
Point() {};
Point(int a, int b) {x=a; y=b;};
bool operator<(const Point &rhs) const {
return ((x < rhs.x)?true:((x == rhs.x)?((y < rhs.y)?true:false):false));
};
};
std::ostream &operator<<(std::ostream &os, const Point &rhs) {
return (os << "x:" << std::setw(3) << rhs.x << " y:" << std::setw(3) << rhs.y << std::setw(0));
};
enum class TreeType : int {
PINE = 1,
CYPRESS = 2,
WILLOW = 3
};
std::ostream &operator<<(std::ostream &os, const enum TreeType &rhs) {
switch(rhs) {
case TreeType::PINE:
os << "PINE"; break;
case TreeType::CYPRESS:
os << "CYPRESS"; break;
case TreeType::WILLOW:
os << "WILLOW"; break;
}
return os;
};
class Tree {
public:
Tree(TreeType type, int height=100) : m_type(type), m_height(height) {m_num=0;};
virtual ~Tree() {};
void height(int height) {m_height = height;};
void point(const Point &point) {m_point = point;};
Tree &operator++() { ++m_num; return *this;};
friend std::ostream &operator<<(std::ostream &os, const Tree &rhs);
protected:
TreeType m_type;
int m_height;
Point m_point;
int m_num;
};
std::ostream &operator<<(std::ostream &os, const Tree &rhs) {
os << "type:" << std::left << std::setw(7) << rhs.m_type
<< std::right << " num:" << std::setw(2) << rhs.m_num
<< " height:" << std::setw(3) << rhs.m_height << " point[" << rhs.m_point << "]";
return os;
}
class PineTree : public Tree {
public:
PineTree(int height=100) : Tree(TreeType::PINE, height) {};
~PineTree() {};
};
class CypressTree : public Tree {
public:
CypressTree(int height=80) : Tree(TreeType::CYPRESS, height) {};
~CypressTree() {};
};
class WillowTree : public Tree {
public:
WillowTree(int height=50) : Tree(TreeType::WILLOW, height) {};
~WillowTree() {};
};
class TreeFactory {
public:
TreeFactory() {std::cout << "TreeFactory()" << std::endl;};
static TreeFactory *getInstance() {
static TreeFactory instance;
return &instance;
}
std::shared_ptr<Tree> getTree(TreeType type) {
std::shared_ptr<Tree> tree;
if(!m_tree_map.empty() && (m_tree_map.count(type) > 0)) {
tree = m_tree_map.at(type);
}else {
switch(type) {
case TreeType::PINE:
tree = std::make_shared<PineTree>(); break;
case TreeType::CYPRESS:
tree = std::make_shared<CypressTree>(); break;
case TreeType::WILLOW:
tree = std::make_shared<WillowTree>(); break;
default:
throw std::string("error tree type!");
}
m_tree_map.insert(std::pair<TreeType, std::shared_ptr<Tree>>(type, tree));
}
++(*tree);
return tree;
}
private:
std::map<TreeType, std::shared_ptr<Tree>> m_tree_map;
};
class Wood {
public:
Wood() {};
~Wood() {};
void addTree(Point point, std::shared_ptr<Tree> tree) {
tree->point(point);
m_tree_map[point] = tree;
};
void print(void) {
for(auto iter : m_tree_map) {
std::cout << "locate[" << std::setw(3) << iter.first.x << "," << std::setw(3) << iter.first.y << "]"
<< std::setw(0) << "\t" << *(iter.second) << "->" << iter.second << std::endl;
}
}
private:
std::map<Point, std::shared_ptr<Tree>> m_tree_map;
};
int main() {
TreeFactory::getInstance();
Wood wood;
std::shared_ptr<Tree> tree_1 = TreeFactory::getInstance()->getTree(TreeType::PINE);
wood.addTree(Point(1,2), tree_1);
std::shared_ptr<Tree> tree_2 = TreeFactory::getInstance()->getTree(TreeType::PINE);
wood.addTree(Point(34,2), tree_2);
std::shared_ptr<Tree> tree_3 = TreeFactory::getInstance()->getTree(TreeType::CYPRESS);
wood.addTree(Point(109,32), tree_3);
std::shared_ptr<Tree> tree_4 = TreeFactory::getInstance()->getTree(TreeType::WILLOW);
wood.addTree(Point(100,12), tree_4);
std::shared_ptr<Tree> tree_5 = TreeFactory::getInstance()->getTree(TreeType::CYPRESS);
wood.addTree(Point(14,232), tree_5);
wood.print();
return 0;
}