设计模式简单代码之Flyweight模式

来源:互联网 发布:胸外扩怎么判断知乎 编辑:程序博客网 时间:2024/05/16 10:50

        在一雨田的Blog有一篇关于Flyweight模式的文章: http://blog.csdn.net/dylgsy/archive/2006/08/10/1045678.aspx

但在编译运行时,问题产生了:出版社和作者显示不了。

 

一雨田原来的代码:

  1. // Flyweight.cpp
  2. #pragma warning(disable: 4786)
  3. #include <iostream>
  4. #include <map>
  5. #include <string>
  6. #include <stdlib.h>
  7. using namespace std;
  8. class Book
  9. {
  10. public:
  11.     string GetPublish() {return *m_publishCompany;}
  12.     string GetWriter()  {return *m_writer;}
  13.     int GetBookID()  {return m_bookID;}
  14.     int GetPrice()  {return m_price;}
  15.     string GetName()    {return m_name;}
  16.     void SetPublish(string *s) {m_publishCompany = s;}
  17.     void SetWriter(string *s) {m_writer = s;}
  18.     void SetBookID(int id)  {m_bookID = id;}
  19.     void SetPrice(int price) {m_price = price;}
  20.     void SetName(string &s)  {m_name = s;}
  21. private:
  22.     string *m_publishCompany; // 出版社
  23.     string *m_writer;   // 作者
  24.     int m_bookID;    // 书籍编号
  25.     int m_price;    // 价钱
  26.     string m_name;    // 书名
  27. };
  28. class PublishFlyweight
  29. {
  30. public:
  31.     PublishFlyweight(string s)
  32.     {
  33.         m_name = s;
  34.     }
  35.     string GetName()
  36.     {
  37.         return m_name;
  38.     }
  39. private:
  40.     string m_name;
  41. };
  42. class PublishFlyweightFactory
  43. {
  44. public:
  45.     PublishFlyweight* GetPublish(string key)
  46.     {
  47.         PublishFlyweight *p;
  48.         map<string, PublishFlyweight*>::iterator it;
  49.         it = mapPublish.find(key);
  50.         // 存在这个出版社
  51.         if(it != mapPublish.end() )
  52.         {
  53.             // 这里可能有点难懂,请查阅STL的帮助文档
  54.             // 其实second就是指 map<string, PublishFlyweight*> 的 PublishFlyweight*
  55.             p = (*it).second;
  56.             cout << "已经有这个出版社: " << p->GetName() << " 你节省了" << strlen(p->GetName().c_str()) << "字节的空间" << endl;
  57.         }
  58.         else
  59.         {// 插入这个PublishFlyweight
  60.             p = new PublishFlyweight(key);
  61.             mapPublish[key] = p;
  62.         }
  63.         return p;
  64.     }
  65. private:
  66.     map<string, PublishFlyweight*> mapPublish;
  67. };
  68. class WriterFlyweight
  69. {
  70. public:
  71.     WriterFlyweight(string s)
  72.     {
  73.         m_name = s;
  74.     }
  75.     string GetName()
  76.     {
  77.         return m_name;
  78.     }
  79. private:
  80.     string m_name;
  81. };
  82. class WriterFlyweightFactory
  83. {
  84. public:
  85.     WriterFlyweight* GetWriter(string key)
  86.     {
  87.         WriterFlyweight *p;
  88.         map<string, WriterFlyweight*>::iterator it;
  89.         it = mapWriter.find(key);
  90.         // 存在这个Writer
  91.         if(it != mapWriter.end() )
  92.         {
  93.             // 这里可能有点难懂,请查阅STL的帮助文档
  94.             // 其实second就是指 map<string, WriterFlyweight*> 的 WriterFlyweight*
  95.             p = (*it).second;
  96.             cout << "已经有这个作者名字: " << p->GetName() << " 你节省了" << strlen(p->GetName().c_str()) << "字节的空间" << endl;
  97.         }
  98.         else
  99.         {// 插入这个PublishFlyweight
  100.             p = new WriterFlyweight(key);
  101.             mapWriter[key] = p;
  102.         }
  103.         return p;
  104.     }
  105. private:
  106.     map<string, WriterFlyweight*> mapWriter; 
  107. };
  108. void ShowBookInfo(Book book)
  109. {
  110.     cout << "书名:" << book.GetName() << endl;
  111.     cout << "编号:" << book.GetBookID() << endl;
  112.     cout << "价钱:" << book.GetPrice() << endl;
  113.     cout << "出版:" << book.GetPublish() << endl;
  114.     cout << "作者:" << book.GetWriter() << endl;
  115.     cout << endl;
  116. }
  117. void main()
  118. {
  119.     PublishFlyweightFactory pff;
  120.     WriterFlyweightFactory wff;
  121.     Book book1, book2, book3;
  122.     book1.SetPublish( &(pff.GetPublish("机械工业出版社")->GetName()) );
  123.     book1.SetWriter( &(wff.GetWriter("候捷")->GetName()) );
  124.     book1.SetBookID(0000);
  125.     book1.SetPrice(20);
  126.     book1.SetName(string("<<C++好野>>"));
  127.     ShowBookInfo(book1);
  128.     book2.SetPublish( &(pff.GetPublish("人民邮电出版社")->GetName()) );
  129.     book2.SetWriter( &(wff.GetWriter("候捷")->GetName()) );
  130.     book2.SetBookID(0001);
  131.     book2.SetPrice(30);
  132.     book2.SetName(string("<<C++是好劲>>"));
  133.     ShowBookInfo(book2);
  134.     book3.SetPublish( &(pff.GetPublish("机械工业出版社")->GetName()) );
  135.     book3.SetWriter( &(wff.GetWriter("一雨田")->GetName()) );
  136.     book3.SetBookID(0002);
  137.     book3.SetPrice(50);
  138.     book3.SetName(string("<<C++无得顶,我是铁头功...>>"));
  139.     ShowBookInfo(book3);
  140.     system("pause");
  141. }

        是什么原因呢?仔细分析其源代码,发现“book1.SetPublish( &(pff.GetPublish("机械工业出版社")->GetName()) );”这一行使用了临时变量,在取“pff.GetPublish("机械工业出版社")->GetName() ”返回一个临时变量,而再取临时变量的地址&,运行到下一行时,这个临时地址将变成一个无效的地址,指向任何值都可以出现。因此,编程中是严禁这样使用的,编程时都应注意此类问题。修改好的代码如下:

  1. /*
  2.  来源:一雨田Blog
  3.  问题:出版社和作者显示不了
  4.  修改:qmroom
  5.  */
  6. // Flyweight.cpp
  7. #include <iostream>
  8. #include <map>
  9. #include <string>
  10. #include <stdlib.h>
  11. using namespace std;
  12. typedef char CHAR;
  13. typedef CHAR *LPSTR;
  14. typedef const CHAR *LPCSTR;
  15. class Book
  16. {
  17. public:
  18.     string GetPublish() {return *m_publishCompany;}
  19.     string GetWriter()  {return *m_writer;}
  20.     int GetBookID()  {return m_bookID;}
  21.     int GetPrice()  {return m_price;}
  22.     string GetName()    {return m_name;}
  23.     void SetPublish(string *s) {m_publishCompany = s;}
  24.     void SetWriter(string *s) {m_writer = s;}
  25.     void SetBookID(int id)  {m_bookID = id;}
  26.     void SetPrice(int price) {m_price = price;}
  27.     void SetName(LPCSTR s)  {m_name = s;}
  28. private:
  29.     string *m_publishCompany; // 出版社
  30.     string *m_writer;   // 作者
  31.     int m_bookID;    // 书籍编号
  32.     int m_price;    // 价钱
  33.     string m_name;    // 书名
  34. };
  35. class PublishFlyweight
  36. {
  37. public:
  38.     PublishFlyweight(string s)
  39.     {
  40.         m_name = new string(s);
  41.     }
  42.     virtual ~PublishFlyweight()
  43.     {
  44.         delete(m_name);
  45.     }
  46.     string *GetName()
  47.     {
  48.         return m_name;
  49.     }
  50. private:
  51.     string *m_name;
  52. };
  53. class PublishFlyweightFactory
  54. {
  55. public:
  56.     PublishFlyweight* GetPublish(string key)
  57.     {
  58.         PublishFlyweight *p;
  59.         map<string, PublishFlyweight*>::iterator it;
  60.         it = mapPublish.find(key);
  61.         // 存在这个出版社
  62.         if(it != mapPublish.end() )
  63.         {
  64.             // 这里可能有点难懂,请查阅STL的帮助文档
  65.             // 其实second就是指 map<string, PublishFlyweight*> 的 PublishFlyweight*
  66.             p = (*it).second;
  67.             cout << "已经有这个出版社: " << *(p->GetName()) << " 你节省了" << strlen((*(p->GetName())).c_str()) << "字节的空间" << endl;
  68.         }
  69.         else
  70.         {
  71.             // 插入这个PublishFlyweight
  72.             p = new PublishFlyweight(key);
  73.             mapPublish[key] = p;
  74.         }
  75.         return p;
  76.     }
  77. private:
  78.     map<string, PublishFlyweight*> mapPublish;
  79. };
  80. class WriterFlyweight
  81. {
  82. public:
  83.     WriterFlyweight(string s)
  84.     {
  85.         m_name = new string(s);
  86.     }
  87.     virtual ~WriterFlyweight()
  88.     {
  89.         delete(m_name);
  90.     }
  91.     string *GetName()
  92.     {
  93.         return m_name;
  94.     }
  95. private:
  96.     string *m_name;
  97. };
  98. class WriterFlyweightFactory
  99. {
  100. public:
  101.     WriterFlyweight* GetWriter(string key)
  102.     {
  103.         WriterFlyweight *p;
  104.         map<string, WriterFlyweight*>::iterator it;
  105.         it = mapWriter.find(key);
  106.         // 存在这个Writer
  107.         if(it != mapWriter.end() )
  108.         {
  109.             // 这里可能有点难懂,请查阅STL的帮助文档
  110.             // 其实second就是指 map<string, WriterFlyweight*> 的 WriterFlyweight*
  111.             p = (*it).second;
  112.             cout << "已经有这个作者名字: " << *(p->GetName()) << " 你节省了" << strlen((*(p->GetName())).c_str()) << "字节的空间" << endl;
  113.         }
  114.         else
  115.         {
  116.             // 插入这个PublishFlyweight
  117.             p = new WriterFlyweight(key);
  118.             mapWriter[key] = p;
  119.         }
  120.         return p;
  121.     }
  122. private:
  123.     map<string, WriterFlyweight*> mapWriter; 
  124. };
  125. void ShowBookInfo(Book book)
  126. {
  127.     cout << "书名:" << book.GetName() << endl;
  128.     cout << "编号:" << book.GetBookID() << endl;
  129.     cout << "价钱:" << book.GetPrice() << endl;
  130.     cout << "出版:" << book.GetPublish() << endl;
  131.     cout << "作者:" << book.GetWriter() << endl;
  132.     cout << endl;
  133. }
  134. void main()
  135. {
  136.     PublishFlyweightFactory pff;
  137.     WriterFlyweightFactory wff;
  138.     Book book1, book2, book3;
  139.     book1.SetPublish( pff.GetPublish("机械工业出版社")->GetName() );
  140.     book1.SetWriter( wff.GetWriter("qmroom")->GetName() );
  141.     book1.SetBookID(0000);
  142.     book1.SetPrice(20);
  143.     book1.SetName(("<<C++好野>>"));
  144.     ShowBookInfo(book1);
  145.     book2.SetPublish( pff.GetPublish("人民邮电出版社")->GetName() );
  146.     book2.SetWriter( wff.GetWriter("qmroom")->GetName() );
  147.     book2.SetBookID(0001);
  148.     book2.SetPrice(30);
  149.     book2.SetName(("<<C++是好劲>>"));
  150.     ShowBookInfo(book2);
  151.     book3.SetPublish( pff.GetPublish("机械工业出版社")->GetName() );
  152.     book3.SetWriter( wff.GetWriter("一雨田")->GetName() );
  153.     book3.SetBookID(0002);
  154.     book3.SetPrice(50);
  155.     book3.SetName(("<<C++无得顶,我是铁头功...>>"));
  156.     ShowBookInfo(book3);
  157.     system("pause");
  158. }

        其实,这段代码还有很多可以修改的地方,以便提高性能和便于维护和使用。请看设计模式简单代码之Flyweight模式(二)

 

下一篇

 

原创粉丝点击