享元模式

享元模式

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

分为两个状态:

内蕴状态存储在享元内部,不会随环境的改变而有所不同,是可以共享的。

外蕴状态是不可以共享的,它随环境的改变而改变的,因此外蕴状态是由客户端来保持(因为环境的变化是由客户端引起的)。

--百度百科

就拿常用的五子棋来进行举例,如果按照常规的实现方式,每次拿出一个棋子的时候就去创建一个新的对象,那么当一盘棋下完的时候,会造成内存的极大浪费,因为很多都是相同的数据。

当分析的时候,会发现每个棋子,相同地方在于材质、大小、形状等等,而不同在于颜色和位置。而当进一步区分,将棋子分为白棋子和黑棋子,那么一类棋子不同就只在于位置不同了,这就会导致在用享元模式实现的时候会有两种方法。

  1. 将棋子分为黑白两种棋子
  2. 将所有棋子视为一种棋子,其中的颜色只是一个外部通过函数进行设定的参数

我选择的是第一种,因此在设定的时候,黑白棋子为两个类,共同的参数就是棋子的材质等等,而不同的在于位置。

对于状态的区分的话,可以视为:

相同的不会通过函数进行改变的就是内部;而需要通过函数进行外部改变的就是外部。

 

我用五子棋进行分析享元模式的时候,遇到了一个问题:都是同一个对象,修改后,前面的一个对象哪里去了。

我最后相通的回答是:

  1. 前面的对象没有被销毁,因为拿五子棋来举例,前一个棋子已经被绘制完了,没有被销毁,因此还是会显示,但是对于是否连线等判断是通过另外一套逻辑进行判断,比如一个矩阵记录所有棋子的位置。而拓展开来就是,享元模式只是提供你所需要的一个对象,去绘制图等等,但是实际涉及到的修改等等是另外一个相附的逻辑。
  2. 另外一种就是理解为再次享元获取,就是以你修改的属性作为标准,再去对象池进行搜寻例如:
string s1 = "abc";
string s2 = "abc";
cout << (s1 == s2) << endl;
s2 = "abcd";
cout << s1 << endl;
cout << s2 << endl;
结果是1.
abc
abcd

可是当你修改一个的时候,只是修改了一个,因为你修改后,s2再去享元数组搜寻,没找到就重新创建了给对象。

 

图片来自《大话设计模式》--享元模式 ,如有侵权,请联系作者进行删除,麻烦了。

 

优点:

  1. 避免重复创建对象,节省内存空间
  2. 随区随用,没有就会被创建,用的时候才会创建
// FlyweightModel.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//

#include <iostream>
#include <map>
#include <string>
using namespace std;

enum EChessType
{
    white = 0,
    black,
};

class CChese
{
   //内部状态
   //可视为绘制棋子的大小、状态、形状等等
protected:
    string m_describe;

protected:
    //外部状态
    //通过外部接口进行设置
    //而在此处将黑白棋子进行了分类,因此在实现的时候就没有提供接口
  
    EChessType m_chessType;
    int m_x;
    int m_y;
public:
    virtual void draw() = 0;
    //void setType(EChessType type) {m_chessType = type}
    void setPoint(int x, int y) { m_x = x; m_y = y; }
};

//关于黑白棋子的具体实现
//关于设计模式种提到的为i共享对象,我目前开发过程中为涉及到
//所以我没有进行描述或者创建
//如果进行猜想,可能适用于规则中的特定标定,类似于某个公司需要的特殊效果等等
class CWhiteChese :public CChese
{
public:
    CWhiteChese(string describe) { 
        m_describe = describe; m_chessType = white;
        cout << "一个白棋子被制造了。" << endl;
    }
    void draw() 
    {
        cout << "在(" << m_x<<","<<m_y<<")处放白色棋子." << endl;
    }
};
class CBlackChese :public CChese
{
public:
    CBlackChese(string describe) {
        m_describe = describe; m_chessType = black; 
        cout << "一个黑棋子被制造了。" << endl;
    }
    void draw()
    {
        cout << "在(" << m_x << "," << m_y << ")处放黑色棋子." << endl;
    }
};
class CCheseFactory
{
private:
    map<int, CChese*> m_chese;
public:
    CCheseFactory() {}
    ~CCheseFactory() 
    {
        map<int, CChese*>::iterator iteror = m_chese.begin();
        for (iteror ; iteror != m_chese.end() ; ++iteror)
        {
            delete iteror->second;
        }
    }

    CChese* getChese(int type)
    {
        map<int, CChese*>::iterator iteror = m_chese.find(type);

        if (iteror != m_chese.end())
        {
            return (CChese*)iteror->second;
        }
        else
        {
            CChese* temp = NULL;
            if (type == white)
            {
                temp = new CWhiteChese("一个旗子的所大小,形状等等。");
                //temp->setType;
            }
            else if (type == black)
            {
                temp = new CBlackChese("一个旗子的所大小,形状等等。");
                //temp->setType;
            }

            if (temp != NULL)
                m_chese[type] = temp;
            return temp;
        }
    }
};
int main()
{
    //工厂
    CCheseFactory fact;
    //白棋子
    CChese* withe1 = fact.getChese(white);
    withe1->setPoint(1, 1);
    withe1->draw();

    CChese* withe2 = fact.getChese(white);
    withe2->setPoint(2, 2);
    withe2->draw();
    
    //黑棋子
    CChese* black1 = fact.getChese(black);
    black1->setPoint(1, 2);
    black1->draw();

    CChese* black2 = fact.getChese(black);
    black2->setPoint(2, 1);
    black2->draw();

    string s1 = "abc";
    string s2 = "abc";
    cout << (s1 == s2) << endl;
    s2 = "abcd";

    cout << s1 << endl;
    cout << s2 << endl;
}

 

 

 

 

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值