11.享元模式

2026-01-22
1102 字 · 6 分钟

设计模式——享元模式

一、基本概念

1. 定义

享元模式(英语:Flyweight Pattern)是一种软件设计模式。它使用物件用来尽可能减少内存使用量;于相似物件中分享尽可能多的资讯。当大量物件近乎重复方式存在,因而使用大量内存时,此法适用。通常物件中的部分状态(state)能够共享。常见做法是把它们放在数据结构外部,当需要使用时再将它们传递给享元。

2. 优缺点

优点

  • 相同对象只要保存一份,这降低了系统中对象的数量,从而降低了系统中细粒度对象给内存带来的压力。

缺点

  • 为了使对象可以共享,需要将一些不能共享的状态外部化,这将增加程序的复杂性;
  • 读取享元模式的外部状态会使得运行时间稍微变长。

3. 结构

  • 抽象享元(Flyweight)角色:是所有的具体享元类的基类,为具体享元规范需要实现的公共接口,非享元的外部状态以参数的形式通过方法传入;
  • 具体享元(Concrete Flyweight)角色:实现抽象享元角色中所规定的接口;
  • 非享元(Unsharable Flyweight)角色:是不可以共享的外部状态,它以参数的形式注入具体享元的相关方法中;
  • 享元工厂(Flyweight Factory)角色:负责创建和管理享元角色。当客户对象请求一个享元对象时,享元工厂检査系统中是否存在符合要求的享元对象,如果存在则提供给客户;如果不存在的话,则创建一个新的享元对象。
classDiagram class Flyweight { <<abstract>> +operation(UnsharedConcreteFlyweight state) void } class ConcreteFlyweight { -string intrinsicState +operation(UnsharedConcreteFlyweight state) void } class UnsharedConcreteFlyweight { -string extrinsicState } class FlyweightFactory { -Map flyweights +getFlyweight(string key) Flyweight } Flyweight <|-- ConcreteFlyweight FlyweightFactory o--> Flyweight : 共享缓存 ConcreteFlyweight ..> UnsharedConcreteFlyweight : 外部状态注入

二、代码实现

非享元角色

抽象享元角色是不可以共享的外部状态,它以参数的形式注入具体享元的相关方法中:

#include <string>
class UnsharedConcreteFlyweight {
public:
explicit UnsharedConcreteFlyweight(std::string info) : info(std::move(info)) {}
std::string getInfo() const {
return info;
}
void setInfo(std::string info) {
this->info = std::move(info);
}
private:
std::string info;
};

抽象享元角色

抽象享元角色是所有的具体享元类的基类,为具体享元规范需要实现的公共接口,非享元的外部状态以参数的形式通过方法传入:

class Flyweight {
public:
virtual ~Flyweight() = default;
virtual void operation(const UnsharedConcreteFlyweight& state) = 0;
};

具体享元角色

具体享元角色实现抽象享元角色中所规定的接口:

#include <iostream>
#include <string>
class ConcreteFlyweight : public Flyweight {
public:
explicit ConcreteFlyweight(const std::string& key) : key(key) {
std::cout << "具体享元" << key << "被创建!" << std::endl;
}
void operation(const UnsharedConcreteFlyweight& state) override {
std::cout << "具体享元" << key << "被调用,";
std::cout << "非享元信息是:" << state.getInfo() << std::endl;
}
private:
std::string key;
};

享元工厂角色

享元工厂角色负责创建和管理享元角色。当客户对象请求一个享元对象时,享元工厂检査系统中是否存在符合要求的享元对象,如果存在则提供给客户;如果不存在的话,则创建一个新的享元对象:

#include <iostream>
#include <memory>
#include <string>
#include <unordered_map>
class FlyweightFactory {
public:
Flyweight* getFlyweight(const std::string& key) {
Flyweight* flyweight = nullptr;
auto it = flyweightHashMap.find(key);
if (it != flyweightHashMap.end()) {
flyweight = it->second.get();
std::cout << "具体享元" << key << "已经存在,被成功获取!" << std::endl;
} else {
auto concrete = std::make_unique<ConcreteFlyweight>(key);
flyweight = concrete.get();
flyweightHashMap.emplace(key, std::move(concrete));
}
return flyweight;
}
private:
std::unordered_map<std::string, std::unique_ptr<Flyweight>> flyweightHashMap;
};

客户类

int main() {
FlyweightFactory factory;
Flyweight* f01 = factory.getFlyweight("a");
Flyweight* f02 = factory.getFlyweight("a");
Flyweight* f11 = factory.getFlyweight("b");
Flyweight* f12 = factory.getFlyweight("b");
f01->operation(UnsharedConcreteFlyweight("第1次调用a。"));
f02->operation(UnsharedConcreteFlyweight("第2次调用a。"));
f11->operation(UnsharedConcreteFlyweight("第1次调用b。"));
f12->operation(UnsharedConcreteFlyweight("第2次调用b。"));
}

运行结果:

具体享元a被创建!
具体享元a已经存在,被成功获取!
具体享元b被创建!
具体享元b已经存在,被成功获取!
具体享元a被调用,非享元信息是:第1次调用a。
具体享元a被调用,非享元信息是:第2次调用a。
具体享元b被调用,非享元信息是:第1次调用b。
具体享元b被调用,非享元信息是:第2次调用b。

参考:


Thanks for reading!

11.享元模式

2026-01-22
1102 字 · 6 分钟

已复制链接

评论区

目录