首页 > 其他分享 >享元模式(flyweight)

享元模式(flyweight)

时间:2023-09-07 18:25:00浏览次数:34  
标签:享元 __ color 模式 对象 shapeMap flyweight circle include

享元模式(flyweight)

1、作用

一些对象在使用一次后就可以销毁了,比如画一个圈,这个对象调用draw()函数后,这个对象就没有作用,除非再次画相同的圈。但是在应用中需要画很多圈,如果每次画一次圈都构造一个对象,这样内存消耗很多,构造销毁也很费时,这个时候就可以考虑一下享元模式,这样可以节省内存的开销。

2、实现方式

享元模式就很像:工厂模式+单例模式

(1)、有一个基类,在工厂中作为统一的接口

(2)、子类是特定功能的类,这类的属性分为两部分:外部属性和内部属性

内部属性:在构造该类的对象的时候就确定了,通过构造函数的参数来设置,不如圆圈的颜色:color。

外部属性:在对象构造以后可以修改,通过setXX()成员函数来设置,比如:圈的半径:radius。

(3)、工厂类:该类有点像单例模式的功能,在特点内部属性的对象已经存在(map中)时,返回存在的对象,不存在时构造一个新对象返回。

img

3、C++代码

Shape.h

#include <iostream>
#include <iomanip>
#include <string>


#ifndef __SHAPE__H__
#define __SHAPE__H__

using namespace std;


class Shape {                   // 如果只有Circle这一种图形的话,可有没必要有这个基类,基类作用就是多态性,所有子类都指向基类。
    virtual void draw() = 0;    // 工厂模式必须有一个基类,应该,要产生很多子类对象,工厂的create统一为成基类对象返回。
};                              // Flyweight模式可以认为是:工厂模式+单例模式


class Circle : public Shape {
    public:

        // 内部属性通过构造函数设置
        Circle(const string &color):color(color) {
            cout<<"new Circle. color:"<<color<<endl;
        } 

        // 外部属性通过set函数设置
        void setX(const int &x) { this->x = x; }
        void setY(const int &y) { this->y = y; }
        void setRadius(const int &r) { this->radius = r; }

        // 可以认为是对象重复利用,一个对象------>多个屏幕上的圈(颜色相同),
        // 那种修改原有对象会影响原有效果的不能对象重用。说白了,这里的circle对象是一次性的,对象调用draw()函数后,就完成了使命,可以销毁
        // flyweight模式则不销毁,以便后续有相同需求的时候使用。
        void draw() {
            cout<<"color:"<<setw(8)<<left<<color<<" radius:"<<setw(5)<<radius<<" coordinate:("<<x<<","<<y<<")"<<endl;
        }
    private:
        string color;
        int x;
        int y;
        int radius;
};



#endif

ShapeFactory.h

#include <iostream>
#include <string>
#include <map>
#include "Shape.h"

#ifndef __SHAPE_FACTORY__H__
#define __SHAPE_FACTORY__H__

using namespace std;

class ShapeFactory {
    public:
    
        // 工厂函数,在没有构造出相应的对象是构造一个加入到对象池中,否则直接取出对象返回。
        static Shape *getCircle(const string &color) {
            if(shapeMap.find(color) == shapeMap.end()) {     // 第一次查找
                shapeMap.insert({color, new Circle(color)});
            }
            return shapeMap[color];                          // 第二次查找
        }
        static Shape *getCircle2(const string &color) {
            auto map_it = shapeMap.find(color);              // 只有这一次查找,代码明显复杂了,如果考虑可读性的话,还是选择第一中比较好。
            if(map_it == shapeMap.end()) {
                auto circle = new Circle(color);
                shapeMap.insert({color, circle});
                return circle;
            } else {
                return map_it->second;      // 这种实现方式少了一次查找过程
            }
        }
    private:
    private:
        // 定义成静态的,所有对象共享这些对象。getCircle也是静态函数,可以不要构造ShapeFactory就能使用。
        static map<string, Shape*> shapeMap;
};

map<string, Shape*> ShapeFactory::shapeMap = map<string, Shape*>(); // 字面值初始化,构造一个对象初始化:类型()

#endif

test.cc

#include "Shape.h"
#include "ShapeFactory.h"

int main() {
    Circle *circle = static_cast<Circle *>(ShapeFactory::getCircle("black"));
    circle->setX(0);
    circle->setY(0);
    circle->setRadius(10);
    circle->draw();


    circle = static_cast<Circle *>(ShapeFactory::getCircle("black"));   // black这个内部属性的对象已经存在,使用原有的对象
    circle->setX(20);                                                   // 设置外部属性
    circle->setY(30);
    circle->setRadius(11);
    circle->draw();

    circle = static_cast<Circle *>(ShapeFactory::getCircle("red"));     // red这个内部属性的对象不存在,新构造一个
    circle->setX(20);                                                   // 设置外部属性
    circle->setY(30);
    circle->setRadius(11);
    circle->draw();

    return 0;
}

输出:

img

标签:享元,__,color,模式,对象,shapeMap,flyweight,circle,include
From: https://www.cnblogs.com/yuandonghua/p/17685759.html

相关文章

  • 代理模式(Proxy)
    代理模式(Proxy)1、作用代理模式是包装一个对象,控制对它的访问,实现逻辑合实现的解耦。2、实现方式代理模式跟装饰器模式、适配器模式、外观模式都有类似的地方,都通过关联关系封装了其他类型的对象,但是使用的目的不一样。代理:包装一个对象,控制对它的访问。装饰者:包装另一个对象......
  • 策略模式(strategy)
    策略模式(Strategy)1、作用策略模式的主要目的主要是将算法的定义(strategy类)和使用分开(context类),也就是将算法的行为和环境分开,将算法的定义放在专门的策略类中,每一个策略类封装一个实现算法。而使用算法的环境中针对抽象策略编程,而不是针对实现编程,符合依赖倒置原则。2、实现方......
  • 模板模式(template)
    模板模式(Template)1、作用做一件是的方法很多,但做这件都可以归纳为几个步骤。这个时候可以使用模板模式,在模板类中,定义做事的步骤,将多种实现做事的细节延迟到子类中去实现。即:定义一个操作中的算法的骨架(模板函数),而将一些步骤延迟到子类中(基本函数)。模板方法使得子类可以不改变......
  • 外观模式(facade)
    外观模式(Facade)1、作用(1)、将各个子系统的接口汇聚在一起,定义一个统一的接口方便客户使用,满足“迪米特法则”,即客户不需要了解子系统,只需要知道Facade模式封装的类即可以使用所有子系统。(2)、隔离用户和子系统,将用户与子系统解耦,当子系统有修改是,顶多修改Facade模式封装的类,无需......
  • 桥接模式
    桥接模式1作用当类的模型有两个或多个维度的时候,如果两个变化维度用同一个类使用继承方式实现会变得很复杂(冗余代码很多),不易于维护和扩展(继承关系是一种强耦合关系),为了降低耦合关系,提高维护性和可扩展性,可以将两个变化维度的通过两个类(abstruction、implementor类)来实现,将两......
  • 韬客时代卷轴模式系统开发介绍和部分核心源码
    韬客时代是一种卷轴模式系统。什么是卷轴模式呢?新用户注册,先送你一部分积分,该积分用于兑换一个初始任务,俗称卷轴!卷轴模式的赚钱的原理是,你用积分兑换初级任务包,完成卷轴任务之后,你可以获得更多的积分,然后复投,达到一定数量后可以兑换更高级的任务包,任务包越高级每次获得的积分也就越......
  • kafka复习:(24)consume-transform-produce模式
    packagecom.cisdi.dsp.modules.metaAnalysis.rest.kafka2023;importorg.apache.kafka.clients.consumer.*;importorg.apache.kafka.clients.producer.KafkaProducer;importorg.apache.kafka.clients.producer.ProducerConfig;importorg.apache.kafka.clients.produc......
  • 区域LIS应用平台 云技术的SaaS模式
    在医疗机构内部,院内实验室主要负责本院临床科室的检验,院内LIS系统必须满足实验室日常的标本处理入库、仪器联机、检验结果处理、报告打印、报告发布、检验信息统计、检验信息报告发布、标本流程、外部医疗机构检验报告调阅等工作。 在医疗机构间,一方面在区域卫生信息平台上构建区......
  • 一文搞定,PO设计模式详解
    PO模式:全称:pageobjece,分层机制,让不同层去做不同类型的事情,让代码结构清晰,增加复⽤性。PO模式的优势:1)效率⾼:同理,PO模式的逻辑层⽅法有具体定义,情况和元素发⽣变化⼀样修改逻辑层,业务层不变。这样看来结构简单清晰,舒服更符合⼈类习惯,普通⽅式就是继续堆case。2)复⽤多收益⼤:同样......
  • 从追MM谈Java的23种设计模式
    1、FACTORY—追MM少不了请吃饭了,麦当劳的鸡翅和肯德基的鸡翅都是MM爱吃的东西,虽然口味有所不同,但不管你带MM去麦当劳或肯德基,只管向服务员说“来四个鸡翅”就行了。麦当劳和肯德基就是生产鸡翅的Factory.以下是引用片段:实例一:publicclassFactory{......