享元模式 (Flyweight Pattern)
意图:运用共享技术有效地支持大量细粒度的对象。
基础组件
- Flyweight (享元接口):声明对象的接口
- ConcreteFlyweight (具体享元):实现享元接口并存储内部状态
- UnsharedConcreteFlyweight (非共享享元):不需要共享的对象
- FlyweightFactory (享元工厂):创建和管理享元对象
- Client (客户端):使用享元对象
继承/实现关系
Flyweight <|-- ConcreteFlyweight
Flyweight <|-- UnsharedConcreteFlyweight
FlyweightFactory --> ConcreteFlyweight (创建和管理)
Client --> FlyweightFactory (获取享元)
Client --> Flyweight (使用)
应用场景
- 系统需要创建大量相似对象
- 对象的大部分状态可以外部化
- 需要减少内存使用
- 对象标识不重要
C++ 实现(游戏粒子系统)
#include <iostream>
#include <string>
#include <unordered_map>
#include <vector>
/*
* 享元模式
* 意图:运用共享技术有效地支持大量细粒度的对象,可以用于减少内存的使用。
* 基础组件:
* - Flyweight (享元接口):声明对象的接口
* - ConcreteFlyweight (具体享元):实现享元接口并存储内部状态
* - UnsharedConcreteFlyweight (非共享享元):不需要共享的对象
* - FlyweightFactory (享元工厂):创建和管理享元对象
* - Client(客户端):使用享元对象
* 继承/实现关系:
* ConcreteFlyweight 实现 Flyweight 接口。
* UnsharedConcreteFlyweight 也实现 Flyweight 接口,但不被共享。
* FlyweightFactory 管理 ConcreteFlyweight 对象的创建和共享。
* Client 使用 FlyweightFactory 获取享元对象并使用它们。
*/
// 享元接口:粒子类型
class ParticleType {
public:
virtual ~ParticleType() = default;
virtual void draw(int x, int y) const = 0;
};
// 具体享元:共享的粒子类型
class SharedParticleType : public ParticleType {
public:
SharedParticleType(const std::string& texture, const std::string& color)
: texture_(texture), color_(color) {}
void draw(int x, int y) const override {
std::cout << "Drawing " << color_ << " particle with "
<< texture_ << " at (" << x << ", " << y << ")\n";
}
private:
std::string texture_; // 内部状态
std::string color_; // 内部状态
};
// 非共享享元:特殊粒子
class UniqueParticle : public ParticleType {
public:
UniqueParticle(const std::string& effect) : effect_(effect) {}
void draw(int x, int y) const override {
std::cout << "Special effect: " << effect_
<< " at (" << x << ", " << y << ")\n";
}
private:
std::string effect_; // 内部状态
};
// 享元工厂
class ParticleFactory {
public:
ParticleType* getParticleType(const std::string& key,
const std::string& texture,
const std::string& color) {
// 检查是否已存在相同的粒子类型
if (particleTypes_.find(key) == particleTypes_.end()) {
// 如果不存在,则创建新的共享粒子类型
particleTypes_[key] = std::make_unique<SharedParticleType>(texture, color);
}
// 返回已存在或新创建的粒子类型(当该粒子已存在时,每次返回的都是同一个对象)
return particleTypes_[key].get();
}
ParticleType* createUniqueParticle(const std::string& effect) {
// 而对于非共享的粒子类型,每次创建都是一个新的对象,返回的也是一个新的对象的指针
uniqueParticles_.push_back(std::make_unique<UniqueParticle>(effect));
return uniqueParticles_.back().get();
}
private:
std::unordered_map<std::string, std::unique_ptr<ParticleType>> particleTypes_;
std::vector<std::unique_ptr<ParticleType>> uniqueParticles_;
};
// 粒子类(包含外部状态)
class Particle {
public:
Particle(ParticleType* type, int x, int y)
: type_(type), x_(x), y_(y) {}
void draw() const {
type_->draw(x_, y_);
}
ParticleType* getType() const {
return type_;
}
private:
ParticleType* type_; // 享元对象
int x_; // 外部状态
int y_; // 外部状态
};
void FlyweightPattern()
{
std::cout << std::string(13, '-') << " Flyweight Pattern " << std::string(13, '-') << std::endl;
ParticleFactory factory;
// 获取共享粒子类型
auto fireType = factory.getParticleType("fire", "fire_texture", "red");
auto waterType = factory.getParticleType("water", "water_texture", "blue");
// 创建特殊粒子
auto explosionType = factory.createUniqueParticle("explosion");
// 创建多个粒子实例
std::vector<Particle> particles;
particles.emplace_back(fireType, 10, 20);
particles.emplace_back(fireType, 15, 25);
particles.emplace_back(waterType, 30, 40);
particles.emplace_back(explosionType, 50, 60);
particles.emplace_back(fireType, 70, 80);
// 绘制所有粒子
for (const auto& particle : particles) {
particle.draw();
}
// 验证共享:相同类型的粒子共享同一个实例
std::cout << "Fire particles share same instance: "
<< "FireType Address:" << std::endl
<< particles[0].getType() << std::endl
<< particles[1].getType() << std::endl
<< particles[4].getType() << std::endl;
}
组件对应关系
ParticleType→ 享元接口SharedParticleType→ 具体享元UniqueParticle→ 非共享享元ParticleFactory→ 享元工厂Particle→ 客户端对象(存储外部状态)
943

被折叠的 条评论
为什么被折叠?



