《设计模式的艺术》笔记 - 享元模式

介绍

享元模式运用共享技术有效地支持大量细粒度对象的复用。系统只使用少量的对象,而这些对象都很相似,状态变化很小,可以实现对象的多次复用。由于享元模式要求能够共享的对象必须是细粒度对象,因此它又称为轻量级模式,是一种对象结构型模式。

实现

myclass.h

cpp 复制代码
//
// Created by yuwp on 2024/1/12.
//

#ifndef DESIGNPATTERNS_MYCLASS_H
#define DESIGNPATTERNS_MYCLASS_H

#include <iostream>
#include <unordered_map>

class Flyweight {   // 享元抽象类
public:
    Flyweight(const std::string &in);
    virtual void operation(const std::string &out) = 0;

    const std::string &getMIn() const;

private:
    std::string m_in;
};

class ConcreteFlyweight : public Flyweight {    // 具体享元类
public:
    ConcreteFlyweight(const std::string &in);

    void operation(const std::string &out) override;
};

class FlyweightFactory {    // 配合工厂模式使用享元工厂类
public:
    ~FlyweightFactory();
    Flyweight *getFlyweight(const std::string &key);
private:
    std::unordered_map<std::string, Flyweight *> m_flyweights;
};

#endif //DESIGNPATTERNS_MYCLASS_H

myclass.cpp

cpp 复制代码
//
// Created by yuwp on 2024/1/12.
//

#include "myclass.h"

Flyweight::Flyweight(const std::string &in) {
    m_in = in;
}

const std::string &Flyweight::getMIn() const {
    return m_in;
}

ConcreteFlyweight::ConcreteFlyweight(const std::string &in) : Flyweight(in) {

}

void ConcreteFlyweight::operation(const std::string &out) {
    std::cout<< "内部状态: " << getMIn() << ", 外部状态: " << out << std::endl;
}

FlyweightFactory::~FlyweightFactory() {
    for (auto it : m_flyweights) {
        if (it.second) {
            delete it.second;
        }
    }
}

Flyweight* FlyweightFactory::getFlyweight(const std::string &key) {
    auto it = m_flyweights.find(key);
    if (it != m_flyweights.end()) {
        return it->second;
    } else {
        Flyweight *flyweight = new ConcreteFlyweight(key);
        m_flyweights.insert(std::make_pair(key, flyweight));
        return flyweight;
    }
}

main.cpp

cpp 复制代码
#include <iostream>
#include <mutex>
#include "myclass.h"

int main() {
    FlyweightFactory *factory = new FlyweightFactory();
    auto fly1 = factory->getFlyweight("a");
    auto fly2 = factory->getFlyweight("b");
    auto fly3 = factory->getFlyweight("a");
    fly1->operation("1");
    fly2->operation("2");
    fly3->operation("3");

    delete factory;

    return 0;
}

总结

优点

  1. 可以极大减少内存中对象的数量,使得相同或相似对象在内存中只保存一份,从而可以节约系统资源,提高系统性能。

  2. 享元模式的外部状态相对独立,而且不会影响其内部状态,从而使得享元对象可以在不同的环境中被共享。

缺点

  1. 享元模式需要分离出内部状态和外部状态,从而使得系统变得复杂,这使得程序的逻辑复杂化。

  2. 为了使对象可以共享,享元模式需要将享元对象的部分状态外部化,而读取外部状态将使得运行时间变长。

适用场景

  1. 一个系统有大量相同或者相似的对象,造成内存的大量耗费。

  2. 对象的大部分状态都可以外部化,可以将这些外部状态传入对象中。

  3. 在使用享元模式时需要维护一个存储享元对象的享元池,而这需要耗费一定的系统资源。因此,在需要多次重复使用同一享元对象时才值得使用享元模式。

练习

myclass.h

cpp 复制代码
//
// Created by yuwp on 2024/1/12.
//

#ifndef DESIGNPATTERNS_MYCLASS_H
#define DESIGNPATTERNS_MYCLASS_H

#include <iostream>
#include <unordered_map>

class Flyweight {   // 享元抽象类
public:
    Flyweight(const std::string &in);
    virtual void display(const std::string &out) = 0;

    const std::string &getMIn() const;

private:
    std::string m_in;
};

class PictureFlyweight : public Flyweight {    // 具体享元类
public:
    PictureFlyweight(const std::string &in);

    void display(const std::string &out) override;
};

class AnimationFlyweight : public Flyweight {    // 具体享元类
public:
    AnimationFlyweight(const std::string &in);

    void display(const std::string &out) override;
};

class VideoFlyweight : public Flyweight {    // 具体享元类
public:
    VideoFlyweight(const std::string &in);

    void display(const std::string &out) override;
};

class FlyweightFactory {    // 配合工厂模式使用享元工厂类
public:
    ~FlyweightFactory();
    Flyweight *getFlyweight(const std::string &key);
    static FlyweightFactory *getInstance();
private:
    FlyweightFactory();

    std::unordered_map<std::string, Flyweight *> m_flyweights;
};

#endif //DESIGNPATTERNS_MYCLASS_H

myclass.cpp

cpp 复制代码
//
// Created by yuwp on 2024/1/12.
//

#include "myclass.h"

Flyweight::Flyweight(const std::string &in) {
    m_in = in;
}

const std::string &Flyweight::getMIn() const {
    return m_in;
}

PictureFlyweight::PictureFlyweight(const std::string &in) : Flyweight(in) {

}

void PictureFlyweight::display(const std::string &out) {
    std::cout << out << ", " << getMIn() << std::endl;
}

AnimationFlyweight::AnimationFlyweight(const std::string &in) : Flyweight(in) {

}

void AnimationFlyweight::display(const std::string &out) {
    std::cout << out << ", " << getMIn() << std::endl;
}

VideoFlyweight::VideoFlyweight(const std::string &in) : Flyweight(in) {

}

void VideoFlyweight::display(const std::string &out) {
    std::cout << out << ", " << getMIn() << std::endl;
}

FlyweightFactory::FlyweightFactory() {

}

FlyweightFactory* FlyweightFactory::getInstance() {
    static FlyweightFactory *factory = new FlyweightFactory();
    return factory;
}

FlyweightFactory::~FlyweightFactory() {
    for (auto it : m_flyweights) {
        if (it.second) {
            delete it.second;
        }
    }
}

Flyweight* FlyweightFactory::getFlyweight(const std::string &key) {
    auto it = m_flyweights.find(key);
    if (it != m_flyweights.end()) {
        return it->second;
    } else {
        Flyweight *flyweight = nullptr;
        if (key == "图片") {
            flyweight = new PictureFlyweight(key);
        } else if (key == "动画") {
            flyweight = new AnimationFlyweight(key);
        } else if (key == "视频") {
            flyweight = new VideoFlyweight(key);
        }
        m_flyweights.insert(std::make_pair(key, flyweight));
        return flyweight;
    }
}

main.cpp

cpp 复制代码
#include <iostream>
#include <mutex>
#include "myclass.h"

int main() {
    FlyweightFactory *factory = FlyweightFactory::getInstance();
    factory->getFlyweight("图片")->display("1");
    factory->getFlyweight("动画")->display("2");
    factory->getFlyweight("视频")->display("3");
    factory->getFlyweight("图片")->display("4");

    return 0;
}
相关推荐
代码小将2 小时前
Leetcode209做题笔记
java·笔记·算法
朗迹 - 张伟2 小时前
UE5 PCG学习笔记
笔记·学习·ue5
寻丶幽风3 小时前
论文阅读笔记——双流网络
论文阅读·笔记·深度学习·视频理解·双流网络
君鼎4 小时前
C++设计模式——单例模式
c++·单例模式·设计模式
敲代码的 蜡笔小新5 小时前
【行为型之中介者模式】游戏开发实战——Unity复杂系统协调与通信架构的核心秘诀
unity·设计模式·c#·中介者模式
令狐前生5 小时前
设计模式学习整理
学习·设计模式
敲代码的 蜡笔小新7 小时前
【行为型之解释器模式】游戏开发实战——Unity动态公式解析与脚本系统的架构奥秘
unity·设计模式·游戏引擎·解释器模式
JANYI20188 小时前
嵌入式设计模式基础--C语言的继承封装与多态
java·c语言·设计模式
sz66cm9 小时前
Linux基础 -- SSH 流式烧录与压缩传输笔记
linux·笔记·ssh
开发游戏的老王10 小时前
[虚幻官方教程学习笔记]深入理解实时渲染(An In-Depth Look at Real-Time Rendering)
笔记·学习·虚幻