【设计模式学习笔记】外观模式和享元模式案例详解(C++实现)

简介: 【设计模式学习笔记】外观模式和享元模式案例详解(C++实现)

一、外观模式

1. 什么是外观模式

Facade Pattern,外观模式,结构型设计模式之一。外观模式为一个子系统集合提供了一个一致的简单界面,并且外观包含了对各个子系统的引用,客户端可以通过这个外观来访问各个子系统。

外观模式中的角色:

  • Facade:外观类,作为调用接口,提供所有子系统的一致访问界面;
  • Clients:通过外观角色来访问各个子系统;
  • Subsystem:子系统,实现子系统的功能;

2. 外观模式案例

首先创建子系统集合,假设为电脑系统,定义显示屏子系统、主机子系统、键盘子系统

1. class Screen //子系统1
2. {
3. public:
4.  void get_attr()
5.  {
6.    cout << "显示屏子系统" << endl;
7.  }
8. };
9. 
10. class Host //子系统2
11. {
12. public:
13.   void get_attr()
14.   {
15.     cout << "主机子系统" << endl;
16.   }
17. };
18. 
19. class Keyboard //子系统3
20. {
21. public:
22.   void get_attr()
23.   {
24.     cout << "键盘子系统" << endl;
25.   }
26. };

如果客户不适应外观类,而是直接访问这个子系统,那么操作将会比较繁琐

1. void Func1()
2. {
3.  Screen* mScreen;
4.  Host* mHost;
5.  Keyboard* mKeyboard;
6. 
7.  mScreen = new Screen;
8.  mHost = new Host;
9.  mKeyboard = new Keyboard;
10. 
11.   mScreen->get_attr();
12.   mHost->get_attr();
13.   mKeyboard->get_attr();
14. }

要创建每个子系统对象,并逐个调用其方法来访问子系统。

创建一个外观类,它包含对所有子系统的引用

1. class Facade
2. {
3. private:
4.  Screen* mScreen;
5.  Host* mHost;
6.  Keyboard* mKeyboard;
7. public:
8.  Facade()
9.  {
10.     mScreen = new Screen;
11.     mHost = new Host;
12.     mKeyboard = new Keyboard;
13.   }
14.   ~Facade()
15.   {
16.     if (mScreen != NULL)
17.     {
18.       delete mScreen;
19.     }
20.     if (mHost != NULL)
21.     {
22.       delete mHost;
23.     }
24.     if (mKeyboard != NULL)
25.     {
26.       delete mKeyboard;
27.     }
28.   }
29.   void get_attr()
30.   {
31.     this->mScreen->get_attr();
32.     this->mHost->get_attr();
33.     this->mKeyboard->get_attr();
34.   }
35. };

通过外观来访问所有子系统

1. void Func2()
2. {
3.  Facade* f = new Facade;
4.  f->get_attr();
5.  delete f;
6. }

二、享元模式

1. 什么是享元模式

Flyweight Pattern,享元模式,结构型设计模式。

在面向对象系统的设计和实现中,创建对象是最常见的操作,这里就会有一个问题:如果一个应用程序使用了太多对象,就会造成很大的存储开销。特别是对于大量轻量级(细粒度)的对象,比如在文档编辑器的设计过程中,我们如果为每一个字母创建一个对象的时候可能会因为大量的对象而造成存储开销的浪费,例如一个字母a在文档中出现了10000次,而实际上我们可以让这10000个a共享一个对象,这种情况下,我们可以将对象状态分为内部状态和外部状态。在享元模式中可以共享(不会变化)的状态称为内部状态(Intrinsic State),而那些需要外部环境来设置的不能共享的内容称为外部状态(Extrinsic State),其中外部状态和内部状态是相互独立的,外部状态的变化不会引起内部状态的变化。内部状态直接存储在对象中,而外部状态(字母a的大小、字体)可以在适当时机作为参数传递给对象。享元模式的目的就是使用共享技术来实现大量细粒度对象的复用。

享元模式的角色:

  • Flyweight:抽象享元角色,定义了所有具体享元类的接口,通过这个接口可以传入外部状态并作用于外部状态;
  • FlyweightFactory:享元工厂,创建并管理享元对象;
  • ConcreteFlyweight:可共享的内部状态;
  • UnsharedConcreteFlyweight:可以不共享的享元子类;

2. 享元模式案例

假设一个字符串和一个标志作为一对,可以通过标志来确定字符串,比如只要传入标志1就得到字符串hello,也就是说,通过flag可以确定一个字符串。

 

1. class MyStr
2. {
3. protected:
4.  string str;
5. public:
6.  MyStr(string str)
7.  {
8.    this->str = str;
9.  }
10.   virtual void get_str() = 0;
11. };
12. 
13. class Hello : public MyStr
14. {
15. private:
16.   int id;
17. public:
18.   Hello(string str, int id) : MyStr(str)
19.   {
20.     this->id = id;
21.   }
22.   virtual void get_str()
23.   {
24.     cout << "id: " << id << "  对应的str:  " << str << endl;
25.   }
26. };

创建一个工厂

1. class Factory
2. {
3. private:
4.  map<int, Hello*> m;
5. public:
6.  ~Factory()
7.  {
8.    while (!m.empty())
9.    {
10.       Hello* tmp = NULL;
11.       map<int, Hello*>::iterator it = m.begin();
12.       tmp = it->second;
13.       m.erase(it);
14.       delete tmp;
15.     }
16.   }
17.   Hello* get_str(int id)
18.   {
19.     Hello* mtemp;
20.     map<int, Hello*>::iterator it;
21.     it = m.find(id);
22.     if (it == m.end())
23.     {
24.       string temp;
25.       cout << "该字符串未找到,请输入字符串:";
26.       cin >> temp;
27.       mtemp = new Hello(temp, id);
28.       m.insert(make_pair(id, mtemp));
29.       return mtemp;
30.     }
31.     else
32.     {
33.       return it->second;
34.     }
35.   }
36. };

客户端通过工厂获取享元对象,并传入一个标志

1. int main()
2. {
3.  Hello* h1 = NULL, * h2 = NULL;
4.  Factory* f = NULL;
5. 
6.  f = new Factory;
7. 
8.  h1 = f->get_str(1);
9.  h1->get_str();
10. 
11.   h2 = f->get_str(1);
12.   h2->get_str();
13. 
14.   delete h2;
15.   delete h1;
16.   delete f;
17. 
18.   system("pause");
19.   return 0;
20. }


相关文章
|
2月前
|
设计模式 数据库连接 PHP
PHP中的设计模式:提升代码的可维护性与扩展性在软件开发过程中,设计模式是开发者们经常用到的工具之一。它们提供了经过验证的解决方案,可以帮助我们解决常见的软件设计问题。本文将介绍PHP中常用的设计模式,以及如何利用这些模式来提高代码的可维护性和扩展性。我们将从基础的设计模式入手,逐步深入到更复杂的应用场景。通过实际案例分析,读者可以更好地理解如何在PHP开发中应用这些设计模式,从而写出更加高效、灵活和易于维护的代码。
本文探讨了PHP中常用的设计模式及其在实际项目中的应用。内容涵盖设计模式的基本概念、分类和具体使用场景,重点介绍了单例模式、工厂模式和观察者模式等常见模式。通过具体的代码示例,展示了如何在PHP项目中有效利用设计模式来提升代码的可维护性和扩展性。文章还讨论了设计模式的选择原则和注意事项,帮助开发者在不同情境下做出最佳决策。
|
2月前
|
编译器 C++
【C++核心】指针和引用案例详解
这篇文章详细讲解了C++中指针和引用的概念、使用场景和操作技巧,包括指针的定义、指针与数组、指针与函数的关系,以及引用的基本使用、注意事项和作为函数参数和返回值的用法。
37 3
|
2月前
|
C++
【C++案例】一个项目掌握C++基础-通讯录管理系统
这篇文章通过一个通讯录管理系统的C++项目案例,详细介绍了如何使用C++实现添加、显示、删除、查找、修改和清空联系人等功能。
42 3
|
2月前
|
设计模式 Java
Java设计模式-外观模式(11)
Java设计模式-外观模式(11)
|
1月前
|
设计模式 Java
Java设计模式之外观模式
这篇文章详细解释了Java设计模式之外观模式的原理及其应用场景,并通过具体代码示例展示了如何通过外观模式简化子系统的使用。
29 0
|
2月前
|
安全 C语言 C++
C++学习笔记
C++学习笔记
|
2月前
|
JavaScript 前端开发 测试技术
一个google Test文件C++语言案例
这篇文章我们来介绍一下真正的C++语言如何用GTest来实现单元测试。
19 0
|
3月前
|
编译器 C++
【C/C++学习笔记】C++声明与定义以及头文件与源文件的用途
【C/C++学习笔记】C++声明与定义以及头文件与源文件的用途
44 0
|
3月前
|
存储 C++
【C/C++学习笔记】string 类型的输入操作符和 getline 函数分别如何处理空白字符
【C/C++学习笔记】string 类型的输入操作符和 getline 函数分别如何处理空白字符
40 0
|
13天前
|
设计模式 安全 Java
Kotlin教程笔记(51) - 改良设计模式 - 构建者模式
Kotlin教程笔记(51) - 改良设计模式 - 构建者模式