一、外观模式
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. }