介绍
享元模式运用共享技术有效地支持大量细粒度对象的复用。系统只使用少量的对象,而这些对象都很相似,状态变化很小,可以实现对象的多次复用。由于享元模式要求能够共享的对象必须是细粒度对象,因此它又称为轻量级模式,是一种对象结构型模式。
实现
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;
}
总结
优点
-
可以极大减少内存中对象的数量,使得相同或相似对象在内存中只保存一份,从而可以节约系统资源,提高系统性能。
-
享元模式的外部状态相对独立,而且不会影响其内部状态,从而使得享元对象可以在不同的环境中被共享。
缺点
-
享元模式需要分离出内部状态和外部状态,从而使得系统变得复杂,这使得程序的逻辑复杂化。
-
为了使对象可以共享,享元模式需要将享元对象的部分状态外部化,而读取外部状态将使得运行时间变长。
适用场景
-
一个系统有大量相同或者相似的对象,造成内存的大量耗费。
-
对象的大部分状态都可以外部化,可以将这些外部状态传入对象中。
-
在使用享元模式时需要维护一个存储享元对象的享元池,而这需要耗费一定的系统资源。因此,在需要多次重复使用同一享元对象时才值得使用享元模式。
练习
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;
}