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

介绍

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

实现

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;
}
相关推荐
User_芊芊君子19 小时前
【Java】设计模式——单例、工厂、代理模式
java·设计模式·代理模式
大筒木老辈子20 小时前
Linux笔记---协议定制与序列化/反序列化
网络·笔记
草莓熊Lotso20 小时前
【C++】递归与迭代:两种编程范式的对比与实践
c语言·开发语言·c++·经验分享·笔记·其他
YA3331 天前
java设计模式二、工厂
java·开发语言·设计模式
我爱挣钱我也要早睡!1 天前
Java 复习笔记
java·开发语言·笔记
汇能感知1 天前
摄像头模块在运动相机中的特殊应用
经验分享·笔记·科技
阿巴Jun1 天前
【数学】线性代数知识点总结
笔记·线性代数·矩阵
茯苓gao1 天前
STM32G4 速度环开环,电流环闭环 IF模式建模
笔记·stm32·单片机·嵌入式硬件·学习
是誰萆微了承諾1 天前
【golang学习笔记 gin 】1.2 redis 的使用
笔记·学习·golang
DKPT1 天前
Java内存区域与内存溢出
java·开发语言·jvm·笔记·学习