享元模式是一种结构性模式
优点:
- 享元模式可以减少内存占用,提高程序的性能。它通过共享对象来减少对象的数量,从而减少内存占用。
- 它可以提高程序的执行速度。由于对象数量减少,程序在运行时需要处理的对象也减少了,因此程序的执行速度会更快。
缺点:
- 享元模式会增加程序的复杂性。您需要将对象的状态分为内部状态和外部状态,并在实现享元对象时考虑如何共享内部状态。
- 它可能会增加程序的维护成本。由于享元模式将对象的创建和使用分离,您需要在客户端代码中管理外部状态,并在使用享元对象时将外部状态传递给它。这可能会增加程序的维护成本。
满足的设计原则:
- 单一职责原则。它将对象的创建和使用分离,使得享元工厂负责创建享元对象,而客户端负责使用享元对象。
- 开放-封闭原则。它允许您在不修改现有代码的情况下添加新的内部状态。您只需要在享元对象中添加新的成员变量并在创建享元对象时初始化它即可。
- 迪米特法则。它将内部状态封装在享元对象中,并通过享元工厂来获取享元对象。客户端不需要直接访问享元对象的内部状态,只需要使用享元工厂来获取享元对象,并在使用享元对象时将外部状态传递给它。
内部与外部状态:
- 内部状态是指对象的固有信息,它不会随着环境的变化而改变。例如,在一个文本编辑器中,每个字符都有一个字体和字号,这些信息是不会改变的,因此它们属于内部状态。
- 外部状态是指对象的外在信息,它会随着环境的变化而改变。例如,在文本编辑器中,每个字符都有一个位置,表示它在文档中的位置。当用户编辑文档时,字符的位置会发生变化,因此它属于外部状态。
- 享元模式通过共享内部状态来减少对象的数量。它将内部状态存储在享元对象中,并在创建享元对象时初始化。
- 客户端可以使用享元工厂来获取享元对象,并在使用享元对象时将外部状态传递给它。
类图:
#include "iostream"
#include "string"
#include "vector"
#include "unordered_map"
using namespace std;
class Flyweight
{
public:
virtual ~Flyweight(){}
virtual void operation(int num)=0;
};
//int num 是外部状态
//string state_; 是内部状态
class ConcreteFlyweight :public Flyweight
{
public:
ConcreteFlyweight(const string& state):state_(state){}
void operation(int num)
{
cout<<"ConcreteFlyweight"<<state_<<num<<endl;
}
private:
string state_;
};
class UnsharedConcreteFlyweight :public Flyweight
{
public:
UnsharedConcreteFlyweight(const string& state) :state_(state) {}
void operation(int num)
{
cout << "UnsharedConcreteFlyweight:" << state_ <<num<< endl;
}
private:
string state_;
};
class FlyweightFactory
{
public:
Flyweight* getFlyweight(const string& key)
{
if (flyweights_.find(key) != flyweights_.end())
{
return flyweights_[key];
}
Flyweight*flyweight=new ConcreteFlyweight(key);
flyweights_[key]=flyweight;
return flyweight;
}
private:
unordered_map<string ,Flyweight*> flyweights_;
};
int main()
{
FlyweightFactory factory;
Flyweight*flyweight1=factory.getFlyweight("A");
Flyweight*flyweight2=factory.getFlyweight("A");
Flyweight*flyweight3=factory.getFlyweight("B");
Flyweight* flyweight4 = new UnsharedConcreteFlyweight("C");
flyweight1->operation(1);
flyweight2->operation(2);
flyweight3->operation(3);
flyweight4->operation(4);
return 0;
}