• 创建型设计模式- C++实现


    创建型模式

    单例模式

    Abstract

    单例模式是一种对象创建型模式,使用单例模式,可以保证为一个类只生成唯一的实例对象。也就是说,在整个程序空间中,该类只存在一个实例对象。

    GoF对单例模式的定义是:保证一个类、只有一个实例存在,同时提供能对该实例加以访问的全局访问方法。

    How

    1. 构造函数私有化

    2. 提供一个全局的静态方法

    3. 在类中定义一个静态指针,指向本类的变量的静态变量指针

    4. 懒汉式单例getInstance 时new, 饿汉式静态函数申明时new

    5. 如果设计单例模板,必须使用懒汉式单例

    Template

    1. #include
    2. #include
    3. #include
    4. using namespace std;
    5. template <typename T>
    6. class Singleton
    7. {
    8. public:
    9. template<typename... Args>
    10. static T* GetInstance(Args&&... args)
    11. {
    12. std::call_once(flag, [&]() {
    13. m_pInstance=new T(std::forward(args)...);
    14. });
    15. return m_pInstance;
    16. }
    17. static void DestroyInstance()
    18. {
    19. delete m_pInstance;
    20. m_pInstance=nullptr;
    21. }
    22. private:
    23. Singleton(void);
    24. virtual ~Singleton(void);
    25. Singleton(const Singleton&);
    26. Singleton& operator =(const Singleton&);
    27. private:
    28. static T* m_pInstance;
    29. static std::once_flag flag;
    30. };
    31. template <class T> T* Singleton::m_pInstance=nullptr;
    32. template <class T> std::once_flag Singleton::flag;
    1. struct A
    2. {
    3. A(){}
    4. };
    5. struct B
    6. {
    7. B(int x){}
    8. };
    9. struct C
    10. {
    11. C(int x,double y){}
    12. };
    13. void function() {
    14. A* a= Singleton::GetInstance();

    简单工厂模式

    Abstract

    简单工厂模式属于类的创建型模式,又叫做静态工厂方法模式。通过专门定义一个类来负责创建其他类的实例,被创建的实例通常都具有共同的父类。

    角色

    1.工厂(Creator)角色

    简单工厂模式的核心,它负责实现创建所有实例的内部逻辑。工厂类可以被外界直接调用,创建所需的产品对象。

    2.抽象(Product)角色

    简单工厂模式所创建的所有对象的父类,它负责描述所有实例所共有的公共接口。

    3.具体产品(Concrete Product)角色

    简单工厂模式所创建的具体实例对象

    优缺点

    在这个模式中,工厂类是整个模式的关键所在。它包含必要的判断逻辑,能够根据外界给定的信息,决定究竟应该创建哪个具体类的对象。用户在使用时可以直接根据工厂类去创建所需的实例,而无需了解这些对象是如何创建以及如何组织的。有利于整个软件体系结构的优化。不难发现,简单工厂模式的缺点也正体现在其工厂类上,由于工厂类集中了所有实例的创建逻辑,所以“高内聚”方面做的并不好。另外,当系统中的具体产品类不断增多时,可能会出现要求工厂类也要做相应的修改,扩展性并不很好。

    Demo

    1. include "iostream"
    2. using namespace std;
    3. //思想: 核心思想是用一个工厂,来根据输入的条件产生不同的类,然后根据不同类的virtual函数得到不同的结果。
    4. //元素分析:
    5. //抽象产品类:水果类
    6. //具体的水果了:香蕉类、苹果类、梨子
    7. //优点 适用于不同情况创建不同的类时
    8. //缺点 客户端必须要知道基类和工厂类,耦合性差 增加一个产品,需要修改工厂类
    9. class Fruit
    10. {
    11. public:
    12. virtual void getFruit() = 0;
    13. protected:
    14. private:
    15. };
    16. class Banana : public Fruit
    17. {
    18. public:
    19. virtual void getFruit()
    20. {
    21. cout<<"香蕉"<
    22. }
    23. protected:
    24. private:
    25. };
    26. class Pear : public Fruit
    27. {
    28. public:
    29. virtual void getFruit()
    30. {
    31. cout<<"梨子"<
    32. }
    33. protected:
    34. private:
    35. };
    36. class Factory
    37. {
    38. public:
    39. static Fruit* Create(char *name)
    40. {
    41. Fruit *tmp = NULL;
    42. if (strcmp(name, "pear") == 0)
    43. {
    44. tmp = new Pear();
    45. }
    46. else if (strcmp(name, "banana") == 0)
    47. {
    48. tmp = new Banana();
    49. }
    50. else
    51. {
    52. return NULL;
    53. }
    54. return tmp;
    55. }
    56. protected:
    57. private:
    58. };
    59. void main()
    60. {
    61. Fruit *pear = Factory::Create("pear");
    62. if (pear == NULL)
    63. {
    64. cout<<"创建pear失败\n";
    65. }
    66. pear->getFruit();
    67. Fruit *banana = Factory::Create("banana");
    68. banana->getFruit();
    69. system("pause");

    工厂模式

    Abstract

    工厂方法模式同样属于类的创建型模式又被称为多态工厂模式。工厂方法模式的意义是定义一个创建产品对象的工厂接口,将实际创建工作推迟到子类当中。

    核心工厂类不再负责产品的创建,这样核心类成为一个抽象工厂角色,仅负责具体工厂子类必须实现的接口,这样进一步抽象化的好处是使得工厂方法模式可以使系统在不修改具体工厂角色的情况下引进新的产品。

    角色

    抽象工厂(Creator)角色

    工厂方法模式的核心,任何工厂类都必须实现这个接口。

    具体工厂(Concrete Creator)角色

    具体工厂类是抽象工厂的一个实现,负责实例化产品对象。

    抽象(Product)角色

    工厂方法模式所创建的所有对象的父类,它负责描述所有实例所共有的公共接口。

    具体产品(Concrete Product)角色

    工厂方法模式所创建的具体实例对象

    Compare

    工厂方法模式与简单工厂模式在结构上的不同不是很明显。工厂方法类的核心是一个抽象工厂类,而简单工厂模式把核心放在一个具体类上。

    工厂方法模式之所以有一个别名叫多态性工厂模式是因为具体工厂类都有共同的接口,或者有共同的抽象父类。

    当系统扩展需要添加新的产品对象时,仅仅需要添加一个具体对象以及一个具体工厂对象,原有工厂对象不需要进行任何修改,也不需要修改客户端,很好的符合了“开放-封闭”原则。而简单工厂模式在添加新产品对象后不得不修改工厂方法,扩展性不好。工厂方法模式退化后可以演变成简单工厂模式。

    “开放-封闭”通过添加代码的方式,不是通过修改代码的方式完成功能的增强。

    Demo

    1. #include "iostream"
    2. using namespace std;
    3. class Fruit
    4. {
    5. public:
    6. virtual void sayname()
    7. {
    8. cout<<"fruit\n";
    9. }
    10. };
    11. class FruitFactory
    12. {
    13. public:
    14. virtual Fruit* getFruit()
    15. {
    16. return new Fruit();
    17. }
    18. };
    19. //香蕉
    20. class Banana : public Fruit
    21. {
    22. public:
    23. virtual void sayname()
    24. {
    25. cout<<"Banana \n"<
    26. }
    27. };
    28. //香蕉工厂
    29. class BananaFactory : public FruitFactory
    30. {
    31. public:
    32. virtual Fruit* getFruit()
    33. {
    34. return new Banana;
    35. }
    36. };
    37. //苹果
    38. class Apple : public Fruit
    39. {
    40. public:
    41. virtual void sayname()
    42. {
    43. cout<<"Apple \n"<
    44. }
    45. };
    46. //苹果工厂
    47. class AppleFactory : public FruitFactory
    48. {
    49. public:
    50. virtual Fruit* getFruit()
    51. {
    52. return new Apple;
    53. }
    54. };
    55. void main()
    56. {
    57. FruitFactory * ff = NULL;
    58. Fruit *fruit = NULL;
    59. //1
    60. ff = new BananaFactory();
    61. fruit = ff->getFruit();
    62. fruit->sayname();
    63. delete fruit;
    64. delete ff;
    65. //2苹果
    66. ff = new AppleFactory();
    67. fruit = ff->getFruit();
    68. fruit->sayname();
    69. delete fruit;
    70. delete ff;
    71. cout<<"hello....\n";
    72. system("pause");
    73. }

    抽象工厂

    Abstract

    抽象工厂模式是所有形态的工厂模式中最为抽象和最其一般性的。抽象工厂模式可以向客户端提供一个接口,使得客户端在不必指定产品的具体类型的情况下,能够创建多个产品族的产品对象。

    工厂模式只能生产一个产品。(要么香蕉、要么苹果)

    抽象工厂可以一下生产一个产品族(里面有很多产品组成

    Role

    1. 抽象工厂(Creator)角色

    抽象工厂模式的核心,包含对多个产品结构的声明,任何工厂类都必须实现这个接口。

    2. 具体工厂(Concrete Creator)角色

    具体工厂类是抽象工厂的一个实现,负责实例化某个产品族中的产品对象。

    3. 抽象(Product)角色

    抽象模式所创建的所有对象的父类,它负责描述所有实例所共有的公共接口。

    4. 具体产品(Concrete Product)角色

    抽象模式所创建的具体实例对象

    Demo

    1. class Fruit
    2. {
    3. public:
    4. virtual void sayname()
    5. {
    6. cout<<"fruit\n";
    7. }
    8. };
    9. class FruitFactory
    10. {
    11. public:
    12. virtual Fruit* getApple()
    13. {
    14. return new Fruit();
    15. }
    16. virtual Fruit* getBanana()
    17. {
    18. return new Fruit();
    19. }
    20. };
    21. //南方香蕉
    22. class SouthBanana : public Fruit
    23. {
    24. public:
    25. virtual void sayname()
    26. {
    27. cout<<"South Banana \n"<
    28. }
    29. };
    30. //南方苹果
    31. class SouthApple : public Fruit
    32. {
    33. public:
    34. virtual void sayname()
    35. {
    36. cout<<"South Apple \n"<
    37. }
    38. };
    39. //北方香蕉
    40. class NorthBanana : public Fruit
    41. {
    42. public:
    43. virtual void sayname()
    44. {
    45. cout<<"North Banana \n"<
    46. }
    47. };
    48. //北方苹果
    49. class NorthApple : public Fruit
    50. {
    51. public:
    52. virtual void sayname()
    53. {
    54. cout<<"North Apple \n"<
    55. }
    56. };
    57. class SourthFruitFactory : public FruitFactory
    58. {
    59. public:
    60. virtual Fruit* getApple()
    61. {
    62. return new SouthApple();
    63. }
    64. virtual Fruit* getBanana()
    65. {
    66. return new SouthBanana();
    67. }
    68. };
    69. class NorthFruitFactory : public FruitFactory
    70. {
    71. public:
    72. virtual Fruit* getApple()
    73. {
    74. return new NorthApple();
    75. }
    76. virtual Fruit* getBanana()
    77. {
    78. return new NorthBanana();
    79. }
    80. };
    81. void main()
    82. {
    83. FruitFactory * ff = NULL;
    84. Fruit *fruit = NULL;
    85. ff = new SourthFruitFactory();
    86. fruit = ff->getApple();
    87. fruit->sayname();
    88. fruit = ff->getBanana();
    89. fruit->sayname();
    90. delete fruit;
    91. delete ff;
    92. ff = new NorthFruitFactory();
    93. fruit = ff->getApple();
    94. fruit->sayname();
    95. fruit = ff->getBanana();
    96. fruit->sayname();
    97. delete fruit;
    98. delete ff;
    99. cout<<"hello....\n";
    100. system("pause");
    101. }

    建造者模式

    Abstract

    Builder模式是为对象的创建而设计的模式- 创建的是一个复合对象:被创建的对象为一个具有复合属性的复合对象- 关注对象创建的各部分的创建过程:不同的工厂(这里指builder生成器)对产品属性有不同的创建方法。

    Role

    1) Builder:为创建产品各个部分,统一抽象接口。

    2) ConcreteBuilder:具体的创建产品的各个部分,部分A, 部分B,部分C。

    3) Director:构造一个使用Builder接口的对象。

    4) Product:表示被构造的复杂对象。

    ConcreteBuilder创建该产品的内部表示并定义它的装配过程,包含定义组成部件的类,包括将这些部件装配成最终产品的接口。

    Compare

    Factory模式中:

    1、有一个抽象的工厂。

    2、实现一个具体的工厂---汽车工厂。

    3、工厂生产汽车A,得到汽车产品A。

    4、工厂生产汽车B,得到汽车产品B。

    这样做,实现了购买者和生产线的隔离。强调的是结果。

    Builder模式:

    1、引擎工厂生产引擎产品,得到汽车部件A。

    2、轮胎工厂生产轮子产品,得到汽车部件B。

    3、底盘工厂生产车身产品,得到汽车部件C。

    4、将这些部件放到一起,形成刚好能够组装成一辆汽车的整体。

    5、将这个整体送到汽车组装工厂,得到一个汽车产品。

    这样做,目的是为了实现复杂对象生产线和其部件的解耦。强调的是过程

    两者的区别在于:

    Factory模式不考虑对象的组装过程,而直接生成一个我想要的对象。

    Builder模式先一个个的创建对象的每一个部件,再统一组装成一个对象。

    Factory模式所解决的问题是,工厂生产产品。

    而Builder模式所解决的问题是工厂控制产品生成器组装各个部件的过程,然后从产品生成器中得到产品。

    Demo

    1. #include
    2. using namespace std;
    3. #include "string"
    4. class House
    5. {
    6. public:
    7. void setFloor(string floor)
    8. {
    9. this->m_floor = floor;
    10. }
    11. void setWall(string wall)
    12. {
    13. this->m_wall = wall;
    14. }
    15. void setDoor(string door)
    16. {
    17. this->m_door = door;
    18. }
    19. //
    20. string getFloor()
    21. {
    22. return m_floor;
    23. }
    24. string setWall()
    25. {
    26. return m_wall;
    27. }
    28. string setDoor()
    29. {
    30. return m_door;
    31. }
    32. protected:
    33. private:
    34. string m_floor;
    35. string m_wall;
    36. string m_door;
    37. };
    38. class Builder
    39. {
    40. public:
    41. virtual void makeFloor() = 0;
    42. virtual void makeWall() = 0;
    43. virtual void makeDoor() = 0;
    44. virtual House *GetHouse() = 0;
    45. };
    46. //公寓
    47. class FlatBuild : public Builder
    48. {
    49. public:
    50. FlatBuild()
    51. {
    52. pHouse = new House;
    53. }
    54. virtual void makeFloor()
    55. {
    56. pHouse->setFloor("flat Door");
    57. }
    58. virtual void makeWall()
    59. {
    60. pHouse->setWall("flat Wall");
    61. }
    62. virtual void makeDoor()
    63. {
    64. pHouse->setDoor("flat Door");
    65. }
    66. virtual House *GetHouse()
    67. {
    68. return pHouse;
    69. }
    70. private:
    71. House *pHouse;
    72. };
    73. //别墅
    74. class VillaBuild : public Builder
    75. {
    76. public:
    77. VillaBuild()
    78. {
    79. pHouse = new House;
    80. }
    81. virtual void makeFloor()
    82. {
    83. pHouse->setFloor("villa floor");
    84. }
    85. virtual void makeWall()
    86. {
    87. pHouse->setWall("villa Wall");
    88. }
    89. virtual void makeDoor()
    90. {
    91. pHouse->setDoor("villa Door");
    92. }
    93. virtual House *GetHouse()
    94. {
    95. return pHouse;
    96. }
    97. private:
    98. House *pHouse;
    99. };
    100. class Director
    101. {
    102. public:
    103. void Construct(Builder *builder)
    104. {
    105. builder->makeFloor();
    106. builder->makeWall();
    107. builder->makeDoor();
    108. }
    109. protected:
    110. private:
    111. };
    112. void main()
    113. {
    114. //客户直接造房子
    115. House *pHose = new House;
    116. pHose->setDoor("wbm门");
    117. pHose->setFloor("wbmFloor");
    118. pHose->setWall("wbmWall");
    119. delete pHose;
    120. /* //工程队直接造房子
    121. Builder *builder = new FlatBuild;
    122. builder->makeFloor();
    123. builder->makeWall();
    124. builder->makeDoor();
    125. */
    126. //指挥者(设计师)指挥 工程队 和 建房子
    127. Director *director = new Director;
    128. //建公寓
    129. Builder *builder = new FlatBuild;
    130. director->Construct(builder); //设计师 指挥 工程队干活
    131. House *house = builder->GetHouse();
    132. cout << house->getFloor() << endl;
    133. delete house;
    134. delete builder;
    135. //建别墅
    136. builder = new VillaBuild;
    137. director->Construct(builder); //设计师 指挥 工程队干活
    138. house = builder->GetHouse();
    139. cout << house->getFloor() << endl;
    140. delete house;
    141. delete builder;
    142. delete director;
    143. system("pause");
    144. return ;
    145. }

    原型模式prototype

    Abstract

    Prototype模式是一种对象创建型模式,它采取复制原型对象的方法来创建对象的实例。使用Prototype模式创建的实例,具有与原型一样的数据。

    1)由原型对象自身创建目标对象。也就是说,对象创建这一动作发自原型对象本身。

    2)目标对象是原型对象的一个克隆。也就是说,通过Prototype模式创建的对象,不仅仅与原型对象具有相同的结构,还与原型对象具有相同的值。

    3)根据对象克隆深度层次的不同,有浅度克隆与深度克隆。

    Demo

    1. class Person
    2. {
    3. public:
    4. virtual Person *Clone() = 0;
    5. virtual void printT() = 0;
    6. };
    7. class JavaProgrammer : public Person
    8. {
    9. public:
    10. JavaProgrammer()
    11. {
    12. this->m_name = "";
    13. this->m_age = 0;
    14. m_resume = NULL;
    15. }
    16. JavaProgrammer(string name, int age)
    17. {
    18. this->m_name = name;
    19. this->m_age = age;
    20. m_resume = NULL;
    21. }
    22. ~JavaProgrammer()
    23. {
    24. if (m_resume!= NULL)
    25. {
    26. free(m_resume);
    27. m_resume = NULL;
    28. }
    29. }
    30. virtual Person *Clone()
    31. {
    32. JavaProgrammer *p = new JavaProgrammer;
    33. *p = *this;
    34. return p;
    35. }
    36. void setResume(char *resume)
    37. {
    38. m_resume = new char[strlen(resume) + 1];
    39. strcpy(m_resume, resume);
    40. }
    41. virtual void printT()
    42. {
    43. cout << "m_name:" << m_name << "\t" << "m_age:" << m_age << endl;
    44. if (m_resume != NULL)
    45. {
    46. cout << m_resume << endl;
    47. }
    48. }
    49. protected:
    50. private:
    51. string m_name;
    52. int m_age;
    53. char *m_resume;
    54. };
    55. void main()
    56. {
    57. JavaProgrammer javaperson1("张三", 30);
    58. javaperson1.setResume("我是java程序员");
    59. Person *p2 = javaperson1.Clone(); //对象具有自我复制功能 注意深拷贝和浅拷贝问题
    60. p2->printT();
    61. delete p2;
    62. cout<<"hello..."<
    63. system("pause");
    64. return ;
    65. }

  • 相关阅读:
    CSS3转换属性—transform之translate、rotate、scale函数详解
    多数据源配置代码
    Day 00 python基础认识与软件安装
    linux_mysql安装教程带安装包(亲测有效)
    JMeter入门教程(10) --函数助手
    git基本操作
    Leetcode刷题详解——全排列 II
    树、二叉树概念(+堆的实现)
    STM32G030F6P6点灯闪烁
    WSL2外部网络设置
  • 原文地址:https://blog.csdn.net/qq_32378713/article/details/126137197