设计模式之享元(flyweight)模式

现在在大力推行节约型社会,“浪费可耻,节俭光荣”。在软件系统中,有时候也会存在资源浪费的情况,例如,在计算机内存中存储了多个完全相同或者非常相似的对象,如果这些对象的数量太多将导致系统运行代价过高。那

大家好,又见面了,我是全栈君,今天给大家准备了Idea注册码。

  现在在大力推行节约型社会,“浪费可耻,节俭光荣”。在软件系统中,有时候也会存在资源浪费的情况,例如,在计算机内存中存储了多个完全相同或者非常相似的对象,如果这些对象的数量太多将导致系统运行代价过高。那么,是否存在一种技术可以用于节约内存使用空间,实现对这些相同或者相似对象的共享访问呢?答案是肯定的,这种技术就是享元模式。

一 享元模式概述

1.1 享元模式简介

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

1.2 享元模式需求

  M公司开发部欲开发一个围棋软件,其界面效果如下图所示:

设计模式之享元(flyweight)模式

  M公司开发人员通过对围棋软件进行分析,发现在围棋棋盘中包含大量的黑子和白子,它们的形状、大小都一模一样,只是出现的位置不同而已。如果将每一个棋子都作为一个独立的对象存储在内存中,将可能导致该围棋软件在运行时所需要的内存空间较大。

  如何降低运行代价、提高系统性能是M公司开发人员需要解决的一个问题。为此,M公司开发人员决定使用享元模式来设计该软件。

1.3 类图

  设计模式之享元(flyweight)模式

1.4 代码实现

1.4.1 抽象棋子类

#pragma once

#include <string>
#include <iostream>
using namespace std;
class AbstractPiece
{
public:
    AbstractPiece(){}
    ~AbstractPiece(){}

    virtual string GetColor() = 0;
    virtual void Display(CCoordinates *pCoodinates) = 0;
};

1.4.2 白色棋子类

class WritePiece : public AbstractPiece
{
public:
    WritePiece()
    {
        cout << "WritePiece Construct" << endl;
    }
    ~WritePiece()
    {
        cout << "WritePiece Deconstruct" << endl;
    }

    string GetColor()
    {
        return "white";
    }

    void Display(CCoordinates *pCoodinates)
    {
        cout << "棋子颜色:"<< GetColor() << "," << 
            "棋子坐标:" << pCoodinates->m_x << "," << pCoodinates->m_y << endl;
    }
};

1.4.5 黑色棋子类

class BlackPiece : public AbstractPiece
{
public:
    BlackPiece()
    {
        cout << "BlackPiece Construct" << endl;
    }
    ~BlackPiece()
    {
        cout << "BlackPiece Deconstruct" << endl;
    }

    string GetColor()
    {
        return "black";
    }

    void Display(CCoordinates *pCoodinates)
    {
        cout << "棋子颜色:"<< GetColor() << "," << 
            "棋子坐标:" << pCoodinates->m_x << "," << pCoodinates->m_y << endl;
    }
};

1.4.6 棋子外部状态类

class CCoordinates
{
public:
    CCoordinates(int x, int y)
    {
        m_x = x;
        m_y = y;
    }
    ~CCoordinates(){}

public:
    int m_x;
    int m_y;
};

1.4.7 棋子工厂类(单例)

#pragma once

#include "flyweight.h"
#include <map>
using namespace std;

class CPieceFactor
{
private:
    CPieceFactor();
    ~CPieceFactor();

public:
    //static CPieceFactor* GetPieceFactorInstance();
    static AbstractPiece* CreatePiece( string strColor );
private:
    typedef map<string, AbstractPiece*> PIECEMAP;
    static PIECEMAP m_PieceVect;
    static CPieceFactor *m_pPieceFactor;
};
#include "PieceFactor.h"

// 饥饿模式的单例模式
CPieceFactor::PIECEMAP CPieceFactor::m_PieceVect;
CPieceFactor * CPieceFactor::m_pPieceFactor = new CPieceFactor();
CPieceFactor::CPieceFactor()
{
    AbstractPiece *pWrite = new WritePiece();
    m_PieceVect.insert(make_pair<string, AbstractPiece*>("write", pWrite));
    AbstractPiece *pBlack = new BlackPiece();
    m_PieceVect.insert(make_pair<string, AbstractPiece*>("black", pBlack));
}

CPieceFactor::~CPieceFactor()
{
    PIECEMAP::iterator iter;
    for (iter = m_PieceVect.begin(); iter != m_PieceVect.end(); iter ++)
    {
        delete iter->second;
    }
}

AbstractPiece* CPieceFactor::CreatePiece( string strColor )
{
    return m_PieceVect[strColor];
}

1.5 测试

#include "stdio.h"

#include "PieceFactor.h"

void main()
{
    // 通过享元工厂获取3颗黑子
    AbstractPiece *pPiece1 = CPieceFactor::CreatePiece("black");
    AbstractPiece *pPiece2 = CPieceFactor::CreatePiece("black");
    AbstractPiece *pPiece3 = CPieceFactor::CreatePiece("black");

    string strCmp;
    strCmp = pPiece1 == pPiece2 ? "相同":"不相同";
    cout << "判断两颗黑子是否相同:" << strCmp.c_str() <<endl;

     // 通过享元工厂获取2颗白子
    AbstractPiece *pPiece4 = CPieceFactor::CreatePiece("write");
    AbstractPiece *pPiece5 = CPieceFactor::CreatePiece("write");
    strCmp = pPiece1 == pPiece2 ? "相同":"不相同";
    cout << "判断两颗白字是否相同:" << strCmp.c_str() <<endl;
    
    // 显示棋子
    pPiece1->Display(new CCoordinates(1,2));
    pPiece2->Display(new CCoordinates(3, 4));
    pPiece3->Display(new CCoordinates(1, 3));
    pPiece4->Display(new CCoordinates(2, 5));
    pPiece5->Display(new CCoordinates(2, 4));

    return;
}

设计模式之享元(flyweight)模式

二 享元模式总结

2.1 主要优点

  可以极大减少内存中对象的数量,使得相同或相似对象在内存中只有一份 => 节省系统资源,提高系统性能!棒棒哒!

2.2 主要缺点

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

2.3 应用场景

  (1)一个系统有大量相同或相似的对象,造成了系统内存的大量损耗 => 赶紧使用享元模式吧!

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

  (3)要维护享元模式,需要耗费一定的系统资源,因为在需要时会多次重复使用才值得使用享元模式了!

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/120137.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • 四、单例模式—不要冒充我,我只有一个! #和设计模式一起旅行#

    单例模式—不要冒充我! 我就是我 是颜色不一样的烟火 天空开阔 要做最坚强的泡沫。——《我就是我》-张国荣有人冒充我给大家说一个秘密了,其实我和设计模式本来并不认识,是相识于网络上,我们聊的很多,聊人生聊梦想,有一天我突然说,设计模式我们一起去旅行吧,她说可以啊!所以才有着一次的旅行。但是总有一些人想要冒充我,因为他们看到了我和设计模式的这场旅行,那么怎么保证“设计…

    2022年2月27日
    46
  • 前端开发中常用的几种设计模式有哪些_设计模式原理

    前端开发中常用的几种设计模式有哪些_设计模式原理设计模式是对软件设计开发过程中反复出现的某类问题的通用解决方案。设计模式更多的是指导思想和方法论,而不是现成的代码,当然每种设计模式都有每种语言中的具体实现方式。学习设计模式更多的是理解各种模式的内在思想和解决的问题,毕竟这是前人无数经验总结成的最佳实践,而代码实现则是对加深理解的辅助。设计模式可以分为三大类:结构型模式(StructuralPatterns):通过识别系统中组件间的简单关系来简化系统的设计。 创建型模式(CreationalPatterns):处理对象的创..

    2022年10月25日
    0
  • 结构性设计模式-适配器模式+桥接模式

    结构性设计模式-适配器模式+桥接模式

    2021年7月13日
    88
  • JAVA设计模式之单例模式

    本文继续介绍23种设计模式系列之单例模式。概念:  java中单例模式是一种常见的设计模式,单例模式的写法有好几种,这里主要介绍三种:懒汉式单例、饿汉式单例、登记式单例。  单例模式有以下特点:  1、单例类只能有一个实例。  2、单例类必须自己创建自己的唯一实例。  3、单例类必须给所有其他对象提供这一实例。  单例模式确保某个类只有一个实例,而且自行实例化并向整个系统提供这个实例…

    2022年3月11日
    35
  • Java内存管理-掌握类加载器的核心源码和设计模式(六)

    勿在流沙筑高台,出来混迟早要还的。做一个积极的人编码、改bug、提升自己我有一个乐园,面向编程,春暖花开!上一篇文章介绍了类加载器分类以及类加载器的双亲委派模型,让我们能够从整体上对类加载器有一个大致的认识,本文会深入到类加载器源码分析,了解类加载器ClassLoader中核心的源码,并且分析ClassLoader中的设计思想或者设计模式! 本文地图:一、ClassLoader核…

    2022年2月28日
    33
  • 设计模式(一)工厂模式Factory(创建型)

    设计模式(一)工厂模式Factory(创建型)设计模式一工厂模式Factory在面向对象编程中,最通常的方法是一个new操作符产生一个对象实例,new操作符就是用来构造对象实例的。但是在一些情况下,new操作符直接生成对象会带来一些问题。举例来说,许多类型对象的创造需要一系列的步骤:你可能需要计算或取得对象的初始设置;选择生成哪个子对象实例;或在生成你需要的对象之前必须先生成一些辅助功能的对象。在这些………

    2022年7月20日
    15

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号