网站建设 质量标准成都网站建设公司哪家专业
news/
2025/9/24 6:06:33/
文章来源:
网站建设 质量标准,成都网站建设公司哪家专业,四川建筑培训网,免费缩短网址系列文章目录
C技能系列 Linux通信架构系列 C高性能优化编程系列 深入理解软件架构设计系列 高级C并发线程编程 设计模式系列
期待你的关注哦#xff01;#xff01;#xff01;
现在的一切都是为将来的梦想编织翅膀#xff0c;让梦想在现实中展翅高飞。 Now everythi…系列文章目录
C技能系列 Linux通信架构系列 C高性能优化编程系列 深入理解软件架构设计系列 高级C并发线程编程 设计模式系列
期待你的关注哦
现在的一切都是为将来的梦想编织翅膀让梦想在现实中展翅高飞。 Now everything is for the future of dream weaving wings, let the dream fly in reality. 结构型设计模式之亨元模式 系列文章目录一、亨元模式介绍二、亨元模式优缺点2.1 优点2.2 缺点 三、亨元模式使用场景四、亨元模式实现五、总结 一、亨元模式介绍
亨元模式不知道为啥起这么奇怪的名字
简单的理解: 一个类的成员非常多创建此对象很消耗资源在实际场景中又需要反复创建和销毁该对象。所消耗的内存就更加庞大。
如果此时设计一个对象池里面缓存一定的对象软件在用时申请不用时回收。就能实现对象的重复利用而多次创建和销毁对象。
什么是享元模式
说到享元模式第一个想到的应该就是池技术了String常量池、数据库连接池、缓冲池等等都是享元模式的应用所以说享元模式是池技术的重要实现方式。
比如我们每次创建字符串对象时都需要创建一个新的字符串对象的话内存开销会很大所以如果第一次创建了字符串对象“adam“下次再创建相同的字符串”adam“时只是把它的引用指向”adam“这样就实现了”adam“字符串再内存中的共享。
举个最简单的例子网络联机下棋的时候一台服务器连接了多个客户端玩家如果我们每个棋子都要创建对象那一盘棋可能就有上百个对象产生玩家多点的话因为内存空间有限一台服务器就难以支持了所以这里要使用享元模式将棋子对象减少到几个实例。
⚠️ 意图 运用共享技术有效地支持大量细粒度的对象。
⚠️ 主要解决 在有大量对象时有可能会造成内存溢出我们把其中共同的部分抽象出来如果有相同的业务请求直接返回在内存中已有的对象避免重新创建。。
⚠️ 何时使用 1、系统中有大量对象。 2、这些对象消耗大量内存。 3、这些对象的状态大部分可以外部化。 4、这些对象可以按照内蕴状态分为很多组当把外蕴对象从对象中剔除出来时每一组对象都可以用一个对象来代替。 5、系统不依赖于这些对象身份这些对象是不可分辨的。
⚠️ 如何解决 用唯一标识码判断如果在内存中有则返回这个唯一标识码所标识的对象。 图1_1 亨元模式类图 因为要求细粒度对象所以不可避免地会使对象数量多且性质相近此时我们就将这些对象的信息分为两个部分内部状态和外部状态。
内部状态指对象共享出来的信息存储在享元对象内部并且不会随环境的改变而改变 外部状态指对象得以依赖的一个标记是随环境改变而改变的、不可共享的状态。
二、亨元模式优缺点
2.1 优点
大大减少了对象的创建降低了程序内存的占用提高效率
享元模式的优点在于它可以极大减少内存中对象的数量使得相同对象或相似对象在内存中只保存一份。享元模式的外部状态相对独立而且不会影响其内部状态从而使得享元对象可以在不同的环境中被共享。
2.2 缺点
提高了系统的复杂度。需要分离出内部状态和外部状态而外部状态具有固化特性不应该随着内部状态的改变而改变
享元模式使得系统更加复杂需要分离出内部状态和外部状态这使得程序的逻辑复杂化。为了使对象可以共享享元模式需要将享元对象的状态外部化而读取外部状态使得运行时间变长。
享元模式可以避免大量非常相似类的开销。在程序设计中有时需要生成大量细粒度的类实例来表示数据。如果能发现这些实例除了几个参数外基本上都是相同的有时就能够大幅度的减少需要实例化的类的数量。如果能把那些参数移到类实例的外面在方法调用时将它们传递进来就可以通过共享大幅度地减少单个实例的数目。
也就是说享元模式Flyweight执行时所需的状态是有内部的也可能有外部的内部状态存储于ConcreteFlyweight对象之中而外部对象则应该考虑由客户端对象存储或计算当调用Flyweight对象的操作时将该状态传递给它。
三、亨元模式使用场景
系统中存在大量相似对象需要缓冲池的场景
注意事项 注意划分内部状态和外部状态否则可能会引起线程安全问题 这些类必须有一个工厂类加以控制。
四、亨元模式实现
Flyweight抽象类 所有具体享元类的超类或接口通过这个接口Flyweight可以接受并作用于外部状态。
#ifndef FLYWEIGHT_FLYWEIGHT_H
#define FLYWEIGHT_FLYWEIGHT_H#include iostream
#include string
#include utilityusing namespace std;
class Flyweight {
public:explicit Flyweight(string extrinsic) {extrinsic_ std::move(extrinsic);}virtual ~Flyweight() default;//定义业务操作virtual void operate(int extrinsic) 0;string getIntrinsic() const {return intrinsic_;}void setIntrinsic(string intrinsic) {intrinsic_ std::move(intrinsic);}public:string intrinsic_; //内部状态
protected://要求享元角色必须接受外部状态string extrinsic_;//外部状态};#endif //FLYWEIGHT_FLYWEIGHT_HConcreteFlyweight类 继承Flyweight超类或实现Flyweight接口并为其内部状态增加存储空间。
#ifndef FLYWEIGHT_CONCRETEFLYWEIGHT_H
#define FLYWEIGHT_CONCRETEFLYWEIGHT_H#include Flyweight.hclass ConcreteFlyweight : public Flyweight{//接受外部状态
public:explicit ConcreteFlyweight(string extrinsic) : Flyweight(std::move(extrinsic)) {}~ ConcreteFlyweight() default;//根据外部状态进行逻辑处理void operate(int extrinsic) override {cout 具体Flyweight: extrinsic endl;}
};#endif //FLYWEIGHT_CONCRETEFLYWEIGHT_HUnsharedConcreteFlyweight类 指那些不需要共享的Flyweight子类。
#ifndef FLYWEIGHT_UNSHAREDCONCRETEFLYWEIGHT_H
#define FLYWEIGHT_UNSHAREDCONCRETEFLYWEIGHT_H#include Flyweight.hclass UnsharedConcreteFlyweight : public Flyweight{
public:explicit UnsharedConcreteFlyweight(string extrinsic) : Flyweight(std::move(extrinsic)) {}~UnsharedConcreteFlyweight() default;//根据外部状态进行逻辑处理void operate(int extrinsic) override {cout 不共享的具体Flyweight: extrinsic endl;}
};#endif //FLYWEIGHT_UNSHAREDCONCRETEFLYWEIGHT_HFlyweightFactory类 一个享元工厂用来创建并管理Flyweight对象主要是用来确保合理地共享Flyweight当用户请求一个Flyweight时FlyweightFactory对象提供一个已创建的实例或创建一个实例。
#include Flyweight.h
#include ConcreteFlyweight.h
#include map
#include memoryusing namespace std;class FlyweightFactory {
public:FlyweightFactory() default;~FlyweightFactory() default;//享元工厂
public:shared_ptrFlyweight GetFlyweight(string extrinsic) {cout extrinsic endl;shared_ptrFlyweight flyweightPtr nullptr;auto a pool_.find(extrinsic);if(pool_.find(extrinsic) ! pool_.end()) { //池中有该对象flyweightPtr pool_.at(extrinsic);cout 已有 extrinsic 直接从池中取---- endl;} else {//根据外部状态创建享元对象flyweightPtr make_sharedConcreteFlyweight(extrinsic);//放入池中pool_.emplace(extrinsic, flyweightPtr);cout 创建 extrinsic 并从池中取出---- endl;}return flyweightPtr;}//定义一个池容器
private:mapstring, shared_ptrFlyweight pool_;
};#endif //FLYWEIGHT_FLYWEIGHTFACTORY_HClient客户端
#include iostream
#include Flyweight.h
#include FlyweightFactory.h
#include UnsharedConcreteFlyweight.husing namespace std;
int main() {int extrinsic 22;FlyweightFactory factory;shared_ptrFlyweight flyweightX factory.GetFlyweight(X);flyweightX-operate(extrinsic);shared_ptrFlyweight flyweightY factory.GetFlyweight(Y);flyweightY-operate(extrinsic);shared_ptrFlyweight flyweightZ factory.GetFlyweight(Z);flyweightZ-operate(extrinsic);shared_ptrFlyweight flyweightReX factory.GetFlyweight(X);flyweightReX-operate(extrinsic);shared_ptrUnsharedConcreteFlyweight unsharedFlyweight make_sharedUnsharedConcreteFlyweight(X) ;unsharedFlyweight-operate(extrinsic);return 0;
}运行结果如下
图1_2 运行结果 从这个结果我们可以看出来第一次创建X、Y、Z时都是先创建再从池中取出而第二次创建X时因为池中已经存在了所以直接从池中取出这就是享元模式。
五、总结
与其他相关模式
客户端要引用享元对象是通过工厂对象创建或者获得的客户端每次引用一个享元对象都是可以通过同一个工厂对象来引用所需要的享元对象。因此可以将享元工厂设计成单例模式这样就可以保证客户端只引用一个工厂实例。因为所有的享元对象都是由一个工厂对象统一管理的所以在客户端没有必要引用多个工厂对象。不管是单纯享元模式还是复合享元模式中的享元工厂角色都可以设计成为单例模式对于结果是不会有任何影响的。
Composite模式Flyweight模式通常和Composite 模式结合起来用共享叶结点的有向无环图实现一个逻辑上的层次结构。复合享元模式实际上是单纯享元模式与合成模式的组合。单纯享元对象可以作为树叶对象来讲是可以共享的而复合享元对象可以作为树枝对象 因此在复合享元角色中可以添加聚集管理方法。通常最好用Flyweight实现State 和Strategy 对象。
小结
享元模式是一个考虑系统性能的设计模式通过使用享元模式可以节约内存空间提高系统的性能。享元模式的核心在于享元工厂类享元工厂类的作用在于提供一个用于存储享元对象的享元池用户需要对象时首先从享元池中获取如果享 元池中不存在则创 建一个新的享元对象返回给用户并在享元池中保存该新增对象。享元模式以共享的方式高效地支持大量的细粒度对象享元对象能做到共享的关键是区分内部状态(Internal State)和外部状态(External State)。 (1) 内部状态是存储在享元对象内部并且不会随环境改变而改变的状态因此内部状态可以共享。 (2) 外部状态是随环境改变而改变的、不可以共享的状态。享元对象的外部状态必须由客户端保存并在享元对象被创建之后在需要使用的时候 再传入到享元对 象内部。一个外部状态与另一个外部状态之间是相互独立的。
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/915034.shtml
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!