设计模式_14 享元模式
14 组合模式
14.1 概念
利用共享技术来有效支持大量细粒度对象的复用。通过共享已经存在的对象来大幅度减少需要创建的对象数量,避免大量相似对象的开销,提高系统资源利用率。
14.2 结构
14.2.1 状态
内部状态:不会随着环境改变而改变的可共享部分。
外部状态:随着环境改变而改变的不可共享部分。
享元模式的实现要领就是区分应用中的这两种状态,并将外部状态外部化。
14.2.2 角色
抽象享元角色:通常是一个接口或抽象类,在抽象享元类中声明了具体享元类公共的方法,这些方法可以向外界提供享元对象的内部状态(内部数据),同时也可以通过这些方法来设置外部状态(外部数据)。
具体享元角色:实现了抽象享元类,称为享元对象。在具体享元类中为内部状态提供了存储空间。通常我们可以结合单例模式来设计具体享元类,为每一个具体享元类提供唯一的享元对象。
非享元角色:并不是所有的抽象享元类的子类都需要被共享,不能被共享的子类可以设计为非共享具体享元类。当需要一个非共享具体享元类的对象时可以直接通过实例化创建。
享元工厂角色:负责创建和管理享元角色。当客户对象请求一个享元对象时,享元工厂检查系统中是否存在符合要求的享元对象,存在则提供给客户,不存在则创建一个新的享元对象。
14.3 实现
俄罗斯方块。方块种类只有几种,但是如果每一个都创建一个实例对象则需占用太多内存空间。
14.3.1 UML图
14.3.2 代码
#include<iostream>
#include<string>
#include<unordered_map>
using namespace std;
class AbstractBox {
public:
virtual string getShape() = 0;
void displayColor(string color) {
cout <<"形状:" << this->getShape() <<" 颜色:" << color << endl;
}
};
class ShapeOne : public AbstractBox {
public:
string getShape() {
return "Shape One";
}
};
class ShapeTwo : public AbstractBox {
public:
string getShape() {
return "Shape Two";
}
};
class ShapeThree : public AbstractBox {
public:
string getShape() {
return "Shape Three";
}
};
class BoxFactory {
private:
unordered_map<string, AbstractBox*> boxMap;
BoxFactory() {
boxMap["one"] = new ShapeOne();
boxMap["two"] = new ShapeTwo();
boxMap["three"] = new ShapeThree();
}
static BoxFactory* factory;
public:
static BoxFactory* getInstance() {
return factory;
}
AbstractBox* getBox(string type) {
return boxMap[type];
}
};
BoxFactory* BoxFactory::factory = new BoxFactory();
int main() {
BoxFactory* factory = BoxFactory::getInstance();
AbstractBox* one = factory->getBox("one");
one->displayColor("red");
AbstractBox* two = factory->getBox("two");
two->displayColor("yello");
AbstractBox* three = factory->getBox("three");
three->displayColor("blue");
return 0;
}
14.4 优缺点
14.4.1 优点
极大减少内存中相似或相同对象数量,节约系统资源。
享元模式中外部状态相对独立,且不影响内部状态。
14.4.2 缺点
为了使对象可以共享,需要将享元对象的部分状态外部化,分离内部状态和外部状态,使程序逻辑复杂。
在使用享元模式时,需要维护一个存储享元对象的享元池,而这需要耗费一定的系统资源。
14.5 使用场景
一个系统有大量相同或相似对象,造成大量内存耗费。
对象的大部分状态都可以外部化,可以将这些外部状态传入对象中。