享元模式 (Flyweight Pattern)

享元模式 (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 → 客户端对象(存储外部状态)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值