如何理解Flyweight模式

这篇文章将为大家详细讲解有关如何理解Flyweight模式,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。

[Flyweight模式]

  
官方描述:

意图
 运用共享技术有效地支持大量细粒度的对象。

适用性 
 1、一个应用程序使用了大量的对象。 
 2、完全由于使用大量的对象,造成很大的存储开销。 
 3、对象的大多数状态都可变为外部状态。 
 4、如果删除对象的外部状态,那么可以用相对较少的共享对象取代很多组对象。 
 5、应用程序不依赖于对象标识。由于Flyweight 对象可以被共享,对于概念上明显有别的对象,标识测试将返回真值。

我的描述:

 在开始设计类的时候,很自然的根据现实情况把某些属性作为类的一部分,例如设计一个图书的管理系统,每本书都有出版社、编号、作者、价钱等的属性,所以这个书的类可以这样设计:

class Book
{
public:
 string GetPublish) {return m_publishCompany;}
 string GetWriter)  {return m_writer;}
 int GetBookID)  {return m_bookID;}
 int GetPrice)  {return m_price;}
 string GetName)    {return m_name;}

 void SetPublishstring &s) {m_publishCompany = s;}
 void SetWriterstring &s) {m_writer = s;}
 void SetBookIDint id)  {m_bookID = id;}
 void SetPriceint price) {m_price = price;}
 void SetNamestring &s)  {m_name = s;}

private:
 string m_publishCompany; // 出版社
 string m_writer;   // 作者
 int m_bookID;    // 书籍编号
 int m_price;    // 价钱
 string m_name;    // 书名
};

 这非常自然。但是随着系统的开发和试运行,这种设计就表现出一些不足的地方了,例如一般图书会非常多,成千上万本,在这些书中可能会有相同的出版社或者相同的作者,那对每本书来说就会重复了,也就是浪费了一些重复的空间。
如果每本书都耗费一些空间,那整个软件系统所耗费的空间是不可想象的。所以,我们就要想办法来解决这个问题。
 高明的面向对象设计者就想出了这个办法,把一些相同的属性(把它叫做“享元”)提取出来,并用一个表来管理(池),这就是Flyweight模式的思想所在。好了,我们现在来看看示意图:

如何理解Flyweight模式
 

 
 这里的ConcreteFlyweight就是需要共享的属性(享元),例如上面的出版社和作者,这里的UnsharedConcreteFlyweight就是
不用共享的属性(书籍编号和价钱)。

    想象一下系统里面Book类的使用:
 1、先看看不用共享模式:
 
 Book book1, book2, book3;
 book1.SetPublish"机械工业出版社");
 book1.SetWriter"候捷");
 book1.SetBookID0000);
 book1.SetPrice20);
 book1.SetName"C++好野");

 book2.SetPublish"人民邮电出版社");
 book2.SetWriter"候捷");
 book2.SetBookID0001);
 book2.SetPrice30);
 book2.SetName"C++是好劲");
 
 book3.SetPublish"机械工业出版社");
 book3.SetWriter"一雨田");
 book3.SetBookID0002);
 book3.SetPrice50);
 book3.SetName"C++无得顶,我是铁头功…"); 
 
 这里有两个“机械工业出版社”和两个“候捷”,重复了。如果使用共享模式的话,这里的浪费就可以避免了。
 别看这里只有两个,想象一下成千上万本书时的空间浪费…

 2、使用共享模式,把出版社和作者两个属性作为享元Fly~~Weight)
 PublishFlyweightFactory pff;
 WriterFlyweightFactory wff;
 Book book1, book2, book3;

 book1.SetPublishpff.GetPublish"机械工业出版社")->GetName));
 book1.SetWriterwff.GetWriter"候捷")->GetName));
 book1.SetBookID0000);
 book1.SetPrice20);
 book1.SetName"C++好野");

 book2.SetPublishpff.GetPublish"人民邮电出版社")->GetName));
 book2.SetWriterwff.GetWriter"候捷")->GetName));
 book2.SetBookID0001);
 book2.SetPrice30);
 book2.SetName"C++是好劲");

 book3.SetPublishpff.GetPublish"机械工业出版社")->GetName));
 book3.SetWriterwff.GetWriter"一雨田")->GetName));
 book3.SetBookID0002);
 book3.SetPrice50);
 book3.SetName"C++无得顶,我是铁头功…");

 为什么使用了PublishFlyweightFactory和WriterFlyweightFactory之后就可以节省空间了呢?

 奥妙就在于GetPublish和GetWriter的实现:
 
 PublishFlyweight* GetPublishstring key)
 {
  PublishFlyweight *p;
  mapPublish::iterator it;
  it = mapPublish.findkey);

  // 存在这个Writer
  ifit != mapPublish.end) )
   p = it;

  else
  {// 插入这个PublishFlyweight
   
   p = new PublishFlyweightkey);
   mapPublish[key] = p;
  }

  return p;
 }
 
 GetWriter的实现大同小异,这里就不列出来了,请看详细代码里的实现。 

下面是完整的代码,可以在一个CPP文件里编译使用,由于使用CSDN提供的插入代码功能会使得整段拷贝有点问题,所以这里还是直接给出代码,并标注颜色,方便大家的拷贝:

// Flyweight.cpp

#pragma warningdisable: 4786)

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

class Book
{
public:
 string GetPublish) {return *m_publishCompany;}
 string GetWriter)  {return *m_writer;}
 int GetBookID)  {return m_bookID;}
 int GetPrice)  {return m_price;}
 string GetName)    {return m_name;}
 
 void SetPublishstring *s) {m_publishCompany = s;}
 void SetWriterstring *s) {m_writer = s;}
 void SetBookIDint id)  {m_bookID = id;}
 void SetPriceint price) {m_price = price;}
 void SetNamestring &s)  {m_name = s;}
 
private:
 string *m_publishCompany; // 出版社
 string *m_writer;   // 作者
 int m_bookID;    // 书籍编号
 int m_price;    // 价钱
 string m_name;    // 书名
};

class PublishFlyweight
{
public:
 PublishFlyweightstring s)
 {
  m_name = s;
 }
 string GetName)
 {
  return m_name;
 }
 
private:
 string m_name;
};

class PublishFlyweightFactory
{
public:
 PublishFlyweight* GetPublishstring key)
 {
  PublishFlyweight *p;
  map<string, PublishFlyweight*>::iterator it;
  it = mapPublish.findkey);
  
  // 存在这个出版社
  ifit != mapPublish.end) )
  {
   // 这里可能有点难懂,请查阅STL的帮助文档
   // 其实second就是指 map<string, PublishFlyweight*> 的 PublishFlyweight*
   p = *it).second;
   cout << "已经有这个出版社: " << p->GetName) << " 你节省了" << strlenp->GetName).c_str)) << "字节的空间" << endl;
  }
  
  else
  {// 插入这个PublishFlyweight
   
   p = new PublishFlyweightkey);
   mapPublish[key] = p;
  }
  
  return p;
 }
 
private:
 map<string, PublishFlyweight*> mapPublish;
};

class WriterFlyweight
{
public:
 WriterFlyweightstring s)
 {
  m_name = s;
 }
 string GetName)
 {
  return m_name;
 }
 
private:
 string m_name;
};

class WriterFlyweightFactory
{
public:
 WriterFlyweight* GetWriterstring key)
 {
  WriterFlyweight *p;
  map<string, WriterFlyweight*>::iterator it;
  it = mapWriter.findkey);
  
  // 存在这个Writer
  ifit != mapWriter.end) )
  {
   // 这里可能有点难懂,请查阅STL的帮助文档
   // 其实second就是指 map<string, WriterFlyweight*> 的 WriterFlyweight*
   p = *it).second;
   cout << "已经有这个作者名字: " << p->GetName) << " 你节省了" << strlenp->GetName).c_str)) << "字节的空间" << endl;
  }
  
  else
  {// 插入这个PublishFlyweight
   
   p = new WriterFlyweightkey);
   mapWriter[key] = p;
  }
  
  return p;
 }
 
private:
 map<string, WriterFlyweight*> mapWriter; 
};

void ShowBookInfoBook book)
{
 cout << "书名:" << book.GetName) << endl;
 cout << "编号:" << book.GetBookID) << endl;
 cout << "价钱:" << book.GetPrice) << endl;
 cout << "出版:" << book.GetPublish) << endl;
 cout << "作者:" << book.GetWriter) << endl;
 cout << endl;
}

void main)
{
 PublishFlyweightFactory pff;
 WriterFlyweightFactory wff;
 Book book1, book2, book3;
 
 book1.SetPublish &pff.GetPublish"机械工业出版社")->GetName)) );
 book1.SetWriter &wff.GetWriter"候捷")->GetName)) );
 book1.SetBookID0000);
 book1.SetPrice20);
 book1.SetNamestring"<<C++好野>>"));
 
 ShowBookInfobook1);
 
 book2.SetPublish &pff.GetPublish"人民邮电出版社")->GetName)) );
 book2.SetWriter &wff.GetWriter"候捷")->GetName)) );
 book2.SetBookID0001);
 book2.SetPrice30);
 book2.SetNamestring"<<C++是好劲>>"));
 
 ShowBookInfobook2);
 
 book3.SetPublish &pff.GetPublish"机械工业出版社")->GetName)) );
 book3.SetWriter &wff.GetWriter"一雨田")->GetName)) );
 book3.SetBookID0002);
 book3.SetPrice50);
 book3.SetNamestring"<<C++无得顶,我是铁头功…>>"));
 
 ShowBookInfobook3);
}

Published by

风君子

独自遨游何稽首 揭天掀地慰生平

发表回复

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