享元模式

特征

复用对象(更准确地说是复用对象的部分属性)

目的

减少对象数量,减轻内存压力。减少对象创建,性能也有一定提升。

详情

五指棋游戏,棋盘上有数量大于2的棋子,但种类只有两种,黑子和白子。除了颜色其余参数完全相同(暂时不说坐标)。

既然如此,我们每次落子时是否需要为该棋子单独创建一个对象呢?至少在该模式下不用。

enum COLOR
{
    C_BLACK = 0,
    C_WHITE = 1,
}

class Chess
{
    Chess(COLOR c,int r = 2);
    draw();

    COLOR color;
    int radius;
    int pos_x;
    int pos_y;
}

上述类中有坐标属性pos_x,pos_y表示在棋盘上的位置,radius表示棋子的半径,color表示棋子颜色,我们这里用它来作为key值区分黑白子。

通常我们需要一个工厂类来作为管理这些对象的工具:

class ChessFactory
{
    static Chess getChess(COLOR c);
    
    static std::map<COLOR,Chess> m_chess;
}
std::map<COLOR,Chess> ChessFactory::m_chess = std::map(0)


Chess ChessFactory::getChess(COLOR c)
{
    if(m_chess.find(c) == m_chess.end())
    {
        m_chess[c] = new Chess(c);
    }
    return m_chess[c];
}

每次落子时我们只需要从该工厂取出棋子便好,如果没有则立即创建,可以想象得到,满棋盘的棋子实际上就只构造了两次。

有个外部环境用于落子:

void play(COLOR c,int pos_x,int pos_y)
{
    Chess chess = ChessFactory::getChess(c);
    chess.pos_x = pos_x;
    chess.pos_y = pos_y;
    chess.draw();
}

不用理会语法,语法肯定有问题的,表达意思就行。

可以看到上面的例子我们仅仅创建了两个对象,用颜色区分。同时对象还有pos_x和pos_y两个坐标属性,棋盘上的每颗棋子的坐标都应该不同,因此这里我们将其作为外部数据传入chess对象中。

这其实也是享元模式的一个特性,我们需要区分外部状态和内部状态,内部状态即上述的坐标属性;外部状态其实就是棋子的半径,即棋子能被复用的特征,或者说固有特性,直接点说就是棋子的外观(一个半径固定的圆)。

总结

精髓在于共享,其次需要区分外部和内部状态。

可能我的理解不到位,欢迎大佬批评指正。

参考

享元模式 | 菜鸟教程 (runoob.com)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值