1.创建型

1.1 单例模式

  • 应用场景
    • 客户端只允许定义一个类的对象
    • 比如某些程序只有一个主窗口
  • 包含的角色类
    • 单例类
  • 特点
    • 单例类的构造函数设为私有,不能直接用构造函数创建对象
    • 单例类提供了一个静态方法供外部获取类的对象
    • 客户端通过静态方法定义单例对象
  • 拓展
    • 饿汉模式/线程安全
    • 懒汉模式
  • UML

01单例模式.png

  • 示例代码 ```cpp

    include

    using namespace std;

class Window{ private: static int counter; static Window* window; Window(){ counter++; }

  1. public:
  2. ~Window(){
  3. counter--;
  4. }
  5. void drawWindow(){
  6. cout << "============" << endl;
  7. cout << "= =" << endl;
  8. cout << "= " << counter << " =" << endl;
  9. cout << "= =" << endl;
  10. cout << "============" << endl;
  11. }
  12. static Window* getWindow(){
  13. if(window == NULL){
  14. window = new Window;
  15. }
  16. return window;
  17. }

}; int Window::counter = 0; Window* Window::window = NULL;

int main(){ Window* w = NULL; int n = 0; while(1){ cout << “888 - 创建窗口” << endl; cin >> n; if(n == 888){ //w = new Window; w = Window::getWindow(); w->drawWindow(); } } return 0; }

  1. <a name="bLuX3"></a>
  2. ## 1.2 原型模式
  3. - 应用场景
  4. - 客户端有一个原型对象,但实际类型未知
  5. - 客户端需要克隆原型对象,创建多个对象
  6. - 包含的角色类
  7. - 抽象原型类
  8. - 具体原型类
  9. - 特点
  10. - 原型模式又叫克隆模式
  11. - 抽象原型类包含clone( )接口
  12. - 具体原型类实现clone( )接口
  13. - 客户端通过原型的clone( )方法获取具体原型对象
  14. - 使用原型模式不用知道原型的具体类型,使用拷贝构造函数需要知道原型的具体类型
  15. - UML
  16. ![02原型模式.png](https://cdn.nlark.com/yuque/0/2021/png/2902589/1633608375740-0d4de163-5630-4c2c-90bf-1e1c5be2a0c1.png#clientId=ubead856f-2f58-4&crop=0&crop=0&crop=1&crop=1&from=ui&height=463&id=u23de3aa3&margin=%5Bobject%20Object%5D&name=02%E5%8E%9F%E5%9E%8B%E6%A8%A1%E5%BC%8F.png&originHeight=617&originWidth=873&originalType=binary&ratio=1&rotation=0&showTitle=false&size=215260&status=done&style=none&taskId=u9a4d6752-3ed9-4742-8f1a-3cd400c79b6&title=&width=655)
  17. - 代码实现
  18. ```cpp
  19. #include <iostream>
  20. using namespace std;
  21. class Monster{
  22. public:
  23. virtual void change(){
  24. cout << "妖怪变身" << endl;
  25. }
  26. virtual Monster* clone(){
  27. return new Monster(*this);
  28. }
  29. };
  30. class Sunwukong : public Monster{
  31. public:
  32. void change(){
  33. cout << "孙悟空变身" << endl;
  34. }
  35. virtual Monster* clone(){
  36. return new Sunwukong(*this);
  37. }
  38. };
  39. class Zhubajie : public Monster{
  40. public:
  41. void change(){
  42. cout << "猪八戒变身" << endl;
  43. }
  44. virtual Monster* clone(){
  45. return new Zhubajie(*this);
  46. }
  47. };
  48. int main(){
  49. Monster* p = NULL;
  50. Monster* fenshen = NULL;
  51. int n;
  52. while(1){
  53. cout << "请输入: 1 -- 孙悟空, 2 -- 猪八戒" << endl;
  54. cin >> n;
  55. switch(n){
  56. case 1 :
  57. p = new Sunwukong;
  58. break;
  59. case 2 :
  60. p = new Zhubajie;
  61. break;
  62. }
  63. p->change();
  64. fenshen = p->clone();
  65. fenshen->change();
  66. }
  67. return 0;
  68. }

1.3 简单工厂模式

  • 应用场景
  • 包含的角色类
  • 特点
    • 抽象产品类定义产品的接口
    • 具体产品类实现产品的接口
    • 工厂类提供创建产品的接口
    • 客户端通过工厂的接口创建具体产品。
    • 增加产品类型时,需修改工厂类,原有的抽象产品类和具体产品类不用修改。
    • 修改工厂类违背了开闭原则,不属于23种设计模式
  • UML

01简单工厂模式.png

  • 代码实现 ```cpp

    include

    using namespace std;

class Toy{ public: virtual void play() = 0; };

class ToyDoll : public Toy{ public: void play(){ cout << “打扮漂亮” << endl; } };

class ToyGun : public Toy{ public: void play(){ cout << “dadada …” << endl; } };

class ToyFactory{ public: Toy createToyDoll(){ return new ToyDoll; } Toy createToyGun(){ return new ToyGun; } };

int main(){ Toy toy = NULL; ToyFactory toyFactory = new ToyFactory; int n;

  1. while(1){
  2. cout << "1 -- 芭比娃娃, 2 -- AK47" << endl;
  3. cin >> n;
  4. switch(n){
  5. case 1 :
  6. toy = toyFactory->createToyDoll();
  7. break;
  8. case 2 :
  9. toy = toyFactory->createToyGun();
  10. break;
  11. }
  12. toy->play();
  13. }
  14. return 0;

}

  1. <a name="kkwmD"></a>
  2. ## 1.4 工厂方法模式
  3. - 应用场景
  4. - 一个工厂生产一个产品
  5. - 增加产品即增加工厂
  6. - 包含的角色类
  7. - 抽象产品类
  8. - 具体产品类
  9. - 抽象工厂类
  10. - 具体工厂类
  11. - 特点
  12. - 抽象产品类,定义产品的接口
  13. - 具体产品类,实现产品的接口
  14. - 抽象工厂类,提供创建产品的接口
  15. - 具体工厂类,实现创建产品的接口
  16. - 增加产品类型时,只需新增工厂类,原有的类都不用修改
  17. - UML
  18. ![02工厂方法模式.png](https://cdn.nlark.com/yuque/0/2021/png/2902589/1633611051370-b6d1db40-a32a-45a2-868b-a2237d024438.png#clientId=ucd76fd51-d4f6-4&crop=0&crop=0&crop=1&crop=1&from=ui&height=444&id=u49abebf2&margin=%5Bobject%20Object%5D&name=02%E5%B7%A5%E5%8E%82%E6%96%B9%E6%B3%95%E6%A8%A1%E5%BC%8F.png&originHeight=592&originWidth=1041&originalType=binary&ratio=1&rotation=0&showTitle=false&size=42701&status=done&style=none&taskId=u199548bf-5cd7-422f-924f-6e939df55fc&title=&width=781)
  19. - 代码实现
  20. ```cpp
  21. #include <iostream>
  22. using namespace std;
  23. class Toy{
  24. public:
  25. virtual void play() = 0;
  26. };
  27. class ToyDoll : public Toy{
  28. public:
  29. void play(){
  30. cout << "打扮漂亮" << endl;
  31. }
  32. };
  33. class ToyGun : public Toy{
  34. public:
  35. void play(){
  36. cout << "dadada ..." << endl;
  37. }
  38. };
  39. class ToyCar : public Toy{
  40. public:
  41. void play(){
  42. cout << "dididi ..." << endl;
  43. }
  44. };
  45. class ToyFactory{
  46. public:
  47. virtual Toy* createToy() = 0;
  48. };
  49. class ToyDollFactory : public ToyFactory{
  50. public:
  51. Toy* createToy(){
  52. return new ToyDoll;
  53. }
  54. };
  55. class ToyGunFactory : public ToyFactory{
  56. public:
  57. Toy* createToy(){
  58. return new ToyGun;
  59. }
  60. };
  61. class ToyCarFactory : public ToyFactory{
  62. public:
  63. Toy* createToy(){
  64. return new ToyCar;
  65. }
  66. };
  67. int main(){
  68. Toy* toy = NULL;
  69. ToyFactory* toyFactory= NULL;
  70. int n;
  71. while(1){
  72. cout << "1 -- 芭比娃娃, 2 -- AK47, 3 -- 玩具车" << endl;
  73. cin >> n;
  74. switch(n){
  75. case 1 :
  76. toyFactory = new ToyDollFactory;
  77. break;
  78. case 2 :
  79. toyFactory = new ToyGunFactory;
  80. break;
  81. case 3 :
  82. toyFactory = new ToyCarFactory;
  83. break;
  84. }
  85. toy = toyFactory->createToy();
  86. toy->play();
  87. }
  88. return 0;
  89. }

2.结构型

2.1 适配器模式

  • 应用场景
    • 现有类已经具备需要的功能,但接口不合适
    • 改造现有类比开发新类成本更低。
  • 包含的角色类
    • 目标接口类
    • 适配器类(现有接口类)
    • 适配器类
  • 特点
    • 目标接口类定义了当前所需要的接口
    • 适配者类为现有的具备所需功能的类
    • 适配器类包装适配器类的接口实现目标接口。
  • UML

03适配器模式.png

  • 代码实现 ```cpp

    include

    using namespace std;

class DomesticVoltage{ public: int output220(){ return 220; } };

class PhoneVoltage{ public: // 供电局不提供5v电压 virtual int output5() = 0; };

class VoltageAdapter : public PhoneVoltage{ private: DomesticVoltage dv; public: VoltageAdapter(DomesticVoltage dv){ this->dv = dv; } int output5(){ return dv->output220() - 215; } };

int main(){ DomesticVoltage domesticVoltage = NULL; VoltageAdapter voltageAdapter = NULL; int n; int inputVoltage = 0; while(1){ cout << “请选择电压:1 — 家用电压, 2 — 手机电压” << endl; cin >> n; switch(n){ case 1 : domesticVoltage = new DomesticVoltage; inputVoltage = domesticVoltage->output220(); break; case 2 : voltageAdapter = new VoltageAdapter(new DomesticVoltage); inputVoltage = voltageAdapter->output5(); break; } if(inputVoltage == 5){ cout << “正在充电” << endl; }else if(inputVoltage > 5){ cout << “手机烧掉” << endl; } } return 0; }

  1. <a name="lDFX9"></a>
  2. # 3.行为型
  3. <a name="N1rV0"></a>
  4. ## 3.1 策略模式
  5. - 应用场景
  6. - 策略需要在运行时才能确定,并且可以自由替换
  7. - 包含的角色类
  8. - 抽象策略类
  9. - 具体策略类
  10. - 环境类
  11. - 特点
  12. - 抽象策略类,定义策略接口
  13. - 具体策略类,实现策略接口
  14. - 环境类,使用策略接口
  15. - UML
  16. ![04策略模式.png](https://cdn.nlark.com/yuque/0/2021/png/2902589/1633612140969-caac7e57-b5b6-4cea-9806-f2b606e28451.png#clientId=u6c7d82cd-93f0-4&crop=0&crop=0&crop=1&crop=1&from=ui&height=342&id=ufd6277ed&margin=%5Bobject%20Object%5D&name=04%E7%AD%96%E7%95%A5%E6%A8%A1%E5%BC%8F.png&originHeight=456&originWidth=919&originalType=binary&ratio=1&rotation=0&showTitle=false&size=257215&status=done&style=none&taskId=u26ac8799-7c52-4f7a-bc79-0ad33757ab4&title=&width=689)
  17. - 代码实现
  18. ```cpp
  19. #include <iostream>
  20. using namespace std;
  21. class Operation{
  22. public:
  23. virtual double calc(double num1, double num2) = 0;
  24. };
  25. class AddOperation : public Operation{
  26. public:
  27. double calc(double num1, double num2){
  28. return num1 + num2;
  29. }
  30. };
  31. class SubOperation : public Operation{
  32. public:
  33. double calc(double num1, double num2){
  34. return num1 - num2;
  35. }
  36. };
  37. class Calculator{
  38. private:
  39. Operation* oprt;
  40. public:
  41. Calculator(Operation* oprt){
  42. this->oprt = oprt;
  43. }
  44. double result(double num1, double num2){
  45. return oprt->calc(num1, num2);
  46. }
  47. };
  48. int main(){
  49. Operation* oprt;
  50. double num1;
  51. double num2;
  52. char opr;
  53. while(1){
  54. cout << "请输入公式, 比如: 1 + 2" << endl;
  55. cin >> num1 >> opr >> num2;
  56. switch(opr){
  57. case '+' :
  58. oprt = new AddOperation;
  59. break;
  60. case '-' :
  61. oprt = new SubOperation;
  62. break;
  63. }
  64. Calculator* calculator = new Calculator(oprt);
  65. cout << calculator->result(num1, num2) << endl;
  66. }
  67. return 0;
  68. }