享元模式(c++实现)

享元模式

模式定义

享元模式(Flyweight),运用共享技术有效的支持大量细粒度的对象。

模式动机

  • 如果一个应用使用了大量的对象,而大量的这些对象造成了很大的存储开销时就应该考虑使用。
  • 当对象的大多数状态可以外部状态,如果删除对象的外部状态,那么可以用相对较少的共享内存对象取代很多组对象,此时可以考虑使用享元模式。

UML类图

源码实现

  • piece.h
#include <string>
enum Color
{
    white,
    black
};
class Piece
{
public:
    Piece(Color color);
    void setPoint(int x, int y);
    Color GetColor() const;
public:
    int     m_X;
    int     m_Y;

private:
    Color     m_Color;
};
  • piece.cpp
#include "piece.h"

Piece::Piece(Color color)
    :m_Color(color)
{

}

void Piece::setPoint(int x, int y)
{
    m_X = x;
    m_Y = y;
}

Color Piece::GetColor() const
{
    return m_Color;
}
  • checkerboard.h
#include <string>
#include "piece.h"
class CheckerBoard
{
public:
    CheckerBoard();
    void Draw();
    void refresh();
    void GetPiece(const Piece& piece);

private:
    std::string     m_Checker;
};
  • checkerboard.cpp
#include <iostream>
#include <string.h>
#include "checkerboard.h"

CheckerBoard::CheckerBoard()
{
    for(int m = 0; m < 20; ++m)
    {
        for(int n = 0; n < 20; ++n)
            m_Checker.append("o");
        m_Checker.append("\n");
    }
}

void CheckerBoard::Draw()
{
    std::cout << m_Checker;
}

void CheckerBoard::refresh()
{
    system("cls");
    std::cout << m_Checker;
}

void CheckerBoard::GetPiece(const Piece& piece)
{
    int pos;
    pos = (piece.m_Y * 21) + piece.m_X;

    if(piece.GetColor() == Color::white)
        m_Checker.replace(pos, 1, "-");
    else if(piece.GetColor() == Color::black)
        m_Checker.replace(pos, 1, "+");
}
  • piecefactory.h
#include <map>
#include "piece.h"
class PieceFactory
{
public:
    PieceFactory();
    Piece *find(Color color);
private:
    std::map<Color, Piece*>     m_PiecesMap;
};
  • piecefactory.cpp
#include <memory>
#include "piecefactory.h"

PieceFactory::PieceFactory()
{

}

Piece *PieceFactory::find(Color color)
{
    auto piece = m_PiecesMap.find(color);
    if(piece != m_PiecesMap.end()){
        return piece->second;
    }
    else
    {
        Piece* p = new Piece(color);
        m_PiecesMap[color] = p;
        return p;
    }
}

  • main.cpp
/************************************
    * @brief	: 享元模式
    * @author	:   wzx
    * @date	:   2020-07-16
    * @project	:  FlyWeight
*************************************/
#include <iostream>
#include <random>
#include <time.h>
#include <thread>
#include <unistd.h>
#include "checkerboard.h"
#include "piecefactory.h"
#include "piece.h"

using namespace std;

void GeneratePoint(Piece* p)
{//随机数生成有点问题
    std::mt19937 rnd(time(0));
    p->m_X = rnd()%20;
    p->m_Y = rnd()%20;
}

int main()
{
    CheckerBoard board;
    board.Draw();

    PieceFactory factory;
    for(int n = 0; n < 20; ++n)
    {
        Piece* p1 = factory.find(Color::black);
        GeneratePoint(p1);

        sleep(1);

        Piece* p2 = factory.find(Color::white);
        GeneratePoint(p2);

        board.GetPiece(*p2);
        board.GetPiece(*p1);
        board.refresh();
    }

    return 0;
}

  • 运行结果

oooooooooooooooooooo

oooooooooo+ooooooooo

-+oooooooooooooooooo

oooooooooooooooooooo

ooooooo-oooo+oo+oooo

oooooooooooooooooooo

o+oooooooooooooooooo

oooo++oo+ooooooooooo

注:随机数生成算法有点问题,这里忽略最终结果

优点

模式的优点

  • 享元模式可以避免大量非常相似类的开销。在程序设计中,有时需要生成大量细粒度的类实例来表示数据。如果能发现这些实例除了几个参数外基本都是相同的,有时就能够受大幅度地减少需要实例化的类的数量。如果能把哪些参数移到类实例的外面,在方法调用的时候将它们传递进来,就可以通过共享大幅度地减少单个实例的数目。

缺点

模式的缺点

  • 使用享元模式需要维护一个记录了系统已有的所有享元的列表,而这本身需要耗费资源。
  • 享元模式使得系统更加的复杂,为了使对象可以共享,需要将一些状态外部化,这是得程序的逻辑复杂化。因此,应当在有足够多的对象实例可供共享时才值得使用享元模式。
posted @ 2020-07-17 15:21  鬼谷子com  阅读(632)  评论(0编辑  收藏  举报