• C++设计模式-创建型设计模式:原型模式


    目录

    原型模式的场景、设计思路、功能

    场景

    如何设计?

    功能:通过克隆来创建新的对象实例


    原型模式的场景、设计思路、功能

    场景

    如何设计?

    老套路,不使用设计模式来设计:

    • 抽象出OrderApi 去处理 HomeOrder 和 AboardOrder,然后调用OrderBussiness来处理
    • 已经有了某个对象实例后,如何快速简单地创建出更多这种对象?
    1. #include
    2. #include
    3. #include
    4. using namespace std;
    5. //转换为string
    6. template<class T>
    7. string iToStr(T& value) {
    8. stringstream ss;
    9. ss << value;
    10. return ss.str();
    11. }
    12. //接口
    13. class OrderApi {
    14. public:
    15. virtual int getOrderProductNum() = 0;
    16. virtual void setOrderProductNum(int num) = 0;
    17. virtual string getOrderContent() = 0;
    18. protected:
    19. OrderApi() {}
    20. };
    21. //国内订单
    22. class HomeOrder :public OrderApi {
    23. public:
    24. int getOrderProductNum() {
    25. return m_orderProductNum;
    26. }
    27. void setOrderProductNum(int num) {
    28. m_orderProductNum = num;
    29. }
    30. string getOrderContent() {
    31. return "本次订单客户:" + m_strCustomerName +
    32. " 订单数量:" + iToStr( m_orderProductNum )+
    33. " 订单ID:" + m_strProductId ;
    34. }
    35. void setCunstomerName(string strCustomerName) {
    36. m_strCustomerName = strCustomerName;
    37. }
    38. string getCumstomerName() {
    39. return m_strCustomerName;
    40. }
    41. void setProductId(string strProductId) {
    42. m_strProductId = strProductId;
    43. }
    44. string getProductId() {
    45. return m_strProductId;
    46. }
    47. private:
    48. string m_strCustomerName;
    49. string m_strProductId;
    50. int m_orderProductNum;
    51. };
    52. //国外订单
    53. class AboardOrder :public OrderApi {
    54. public:
    55. int getOrderProductNum() {
    56. return m_orderProductNum;
    57. }
    58. void setOrderProductNum(int num) {
    59. m_orderProductNum = num;
    60. }
    61. string getOrderContent() {
    62. return "本次订单客户:" + m_strCustomerName +
    63. " 订单数量:" + iToStr(m_orderProductNum) +
    64. " 订单ID:" + m_strProductId;
    65. }
    66. void setCunstomerName(string strCustomerName) {
    67. m_strCustomerName = strCustomerName;
    68. }
    69. string getCumstomerName() {
    70. return m_strCustomerName;
    71. }
    72. void setProductId(string strProductId) {
    73. m_strProductId = strProductId;
    74. }
    75. string getProductId() {
    76. return m_strProductId;
    77. }
    78. private:
    79. string m_strCustomerName;
    80. string m_strProductId;
    81. int m_orderProductNum;
    82. };
    83. //订单业务
    84. class OrderBusiness {
    85. public:
    86. void saveOrder(OrderApi* pOrder) {
    87. //判断工件数量是否超过200
    88. while (pOrder->getOrderProductNum() > 200) {
    89. //新建一个订单
    90. //问题来了,这时候根本不知道传入的是国内还是国外地订单
    91. OrderApi* pNewOrder = nullptr;
    92. if (dynamic_cast(pOrder) != nullptr) {
    93. //创建一个新对象
    94. HomeOrder* p2 = new HomeOrder;
    95. //赋值对象
    96. HomeOrder* p1 = static_cast(pOrder);
    97. p2->setOrderProductNum(200);
    98. p2->setCunstomerName(p1->getCumstomerName());
    99. p2->setProductId(p1->getProductId());
    100. pNewOrder = p2;
    101. }
    102. //海外订单
    103. if (dynamic_cast(pOrder) != nullptr) {
    104. //创建一个新对象
    105. AboardOrder* p2 = new AboardOrder;
    106. //赋值对象
    107. AboardOrder* p1 = static_cast(pOrder);
    108. p2->setOrderProductNum(200);
    109. p2->setCunstomerName(p1->getCumstomerName());
    110. p2->setProductId(p1->getProductId());
    111. pNewOrder = p2;
    112. }
    113. //原来的订单,还是保留,但数量要减少200
    114. pOrder->setOrderProductNum(pOrder->getOrderProductNum() - 200);
    115. cout << "新订单:" << pNewOrder->getOrderContent() << endl;
    116. }
    117. //不超过200个
    118. cout << " 最终订单: " << pOrder->getOrderContent() << endl;
    119. }
    120. };
    121. int main() {
    122. HomeOrder* pHome = new HomeOrder;
    123. pHome->setOrderProductNum(512);
    124. pHome->setCunstomerName("yxh");
    125. pHome->setProductId("C++ pattern");
    126. OrderBusiness* pOb = new OrderBusiness;
    127. pOb->saveOrder(pHome);
    128. return 0;
    129. }

    可以运行,但有什么问题?

    同样的,在Builder模式中,重构前有大量重复冗余地代码,在这里也一样,有重复冗余的if 语句,

    这里就应该重构。

    DRY原则:Don't Repeat yourself!

    重构:

    1. #include
    2. #include
    3. #include
    4. using namespace std;
    5. //转换为string
    6. template<class T>
    7. string iToStr(T& value) {
    8. stringstream ss;
    9. ss << value;
    10. return ss.str();
    11. }
    12. //接口
    13. class OrderApi {
    14. public:
    15. virtual int getOrderProductNum() = 0;
    16. virtual void setOrderProductNum(int num) = 0;
    17. virtual string getOrderContent() = 0;
    18. //重构
    19. virtual OrderApi* cloneOrder() = 0;
    20. protected:
    21. OrderApi() {}
    22. };
    23. //国内订单
    24. class HomeOrder :public OrderApi {
    25. public:
    26. int getOrderProductNum() {
    27. return m_orderProductNum;
    28. }
    29. void setOrderProductNum(int num) {
    30. m_orderProductNum = num;
    31. }
    32. string getOrderContent() {
    33. return "本次订单客户:" + m_strCustomerName +
    34. " 订单数量:" + iToStr(m_orderProductNum) +
    35. " 订单ID:" + m_strProductId;
    36. }
    37. void setCunstomerName(string strCustomerName) {
    38. m_strCustomerName = strCustomerName;
    39. }
    40. string getCumstomerName() {
    41. return m_strCustomerName;
    42. }
    43. void setProductId(string strProductId) {
    44. m_strProductId = strProductId;
    45. }
    46. string getProductId() {
    47. return m_strProductId;
    48. }
    49. //重构
    50. OrderApi* cloneOrder() {
    51. HomeOrder* pHomeOrder = new HomeOrder;
    52. pHomeOrder->setCunstomerName(m_strCustomerName);
    53. pHomeOrder->setProductId(m_strProductId);
    54. pHomeOrder->setOrderProductNum(m_orderProductNum);
    55. return pHomeOrder;
    56. }
    57. private:
    58. string m_strCustomerName;
    59. string m_strProductId;
    60. int m_orderProductNum;
    61. };
    62. //国外订单
    63. class AboardOrder :public OrderApi {
    64. public:
    65. int getOrderProductNum() {
    66. return m_orderProductNum;
    67. }
    68. void setOrderProductNum(int num) {
    69. m_orderProductNum = num;
    70. }
    71. string getOrderContent() {
    72. return "本次订单客户:" + m_strCustomerName +
    73. " 订单数量:" + iToStr(m_orderProductNum) +
    74. " 订单ID:" + m_strProductId;
    75. }
    76. void setCunstomerName(string strCustomerName) {
    77. m_strCustomerName = strCustomerName;
    78. }
    79. string getCumstomerName() {
    80. return m_strCustomerName;
    81. }
    82. void setProductId(string strProductId) {
    83. m_strProductId = strProductId;
    84. }
    85. string getProductId() {
    86. return m_strProductId;
    87. }
    88. //重构
    89. OrderApi* cloneOrder() {
    90. AboardOrder* pAboardOrder = new AboardOrder;
    91. pAboardOrder->setCunstomerName(m_strCustomerName);
    92. pAboardOrder->setProductId(m_strProductId);
    93. pAboardOrder->setOrderProductNum(m_orderProductNum);
    94. return pAboardOrder;
    95. }
    96. private:
    97. string m_strCustomerName;
    98. string m_strProductId;
    99. int m_orderProductNum;
    100. };
    101. //订单业务
    102. class OrderBusiness {
    103. public:
    104. void saveOrder(OrderApi* pOrder) {
    105. //判断工件数量是否超过200
    106. while (pOrder->getOrderProductNum() > 200) {
    107. //新建一个订单
    108. //重构
    109. OrderApi* pNewOrder = pOrder->cloneOrder();
    110. pNewOrder->setOrderProductNum(200);
    111. //原来的订单,还是保留,但数量要减少200
    112. pOrder->setOrderProductNum(pOrder->getOrderProductNum() - 200);
    113. cout << "新订单:" << pNewOrder->getOrderContent() << endl;
    114. }
    115. //不超过200个
    116. cout << " 最终订单: " << pOrder->getOrderContent() << endl;
    117. }
    118. };
    119. int main() {
    120. HomeOrder* pHome = new HomeOrder;
    121. pHome->setOrderProductNum(512);
    122. pHome->setCunstomerName("yxh");
    123. pHome->setProductId("C++ pattern");
    124. OrderBusiness* pOb = new OrderBusiness;
    125. pOb->saveOrder(pHome);
    126. return 0;
    127. }

    结果是一样的。

    其核心部分在于,将之前的:

    1. OrderApi* pNewOrder = nullptr;
    2. if (dynamic_cast(pOrder) != nullptr) {
    3. //创建一个新对象
    4. HomeOrder* p2 = new HomeOrder;
    5. //赋值对象
    6. HomeOrder* p1 = static_cast(pOrder);
    7. p2->setOrderProductNum(200);
    8. p2->setCunstomerName(p1->getCumstomerName());
    9. p2->setProductId(p1->getProductId());
    10. pNewOrder = p2;
    11. }
    12. //海外订单
    13. if (dynamic_cast(pOrder) != nullptr) {
    14. //创建一个新对象
    15. AboardOrder* p2 = new AboardOrder;
    16. //赋值对象
    17. AboardOrder* p1 = static_cast(pOrder);
    18. p2->setOrderProductNum(200);
    19. p2->setCunstomerName(p1->getCumstomerName());
    20. p2->setProductId(p1->getProductId());
    21. pNewOrder = p2;
    22. }

    重构为两个部分:

    1. //重构
    2. OrderApi* cloneOrder() {
    3. HomeOrder* pHomeOrder = new HomeOrder;
    4. pHomeOrder->setCunstomerName(m_strCustomerName);
    5. pHomeOrder->setProductId(m_strProductId);
    6. pHomeOrder->setOrderProductNum(m_orderProductNum);
    7. return pHomeOrder;
    8. }
    1. //重构
    2. OrderApi* cloneOrder() {
    3. AboardOrder* pAboardOrder = new AboardOrder;
    4. pAboardOrder->setCunstomerName(m_strCustomerName);
    5. pAboardOrder->setProductId(m_strProductId);
    6. pAboardOrder->setOrderProductNum(m_orderProductNum);
    7. return pAboardOrder;
    8. }

    功能:通过克隆来创建新的对象实例

    为克隆出来的新的对象实例复制原型实例属性的值

  • 相关阅读:
    conda与pip镜像源环境配置
    【Spring boot 整合 JPA 保存数据和Spring boot 使用 JdbcTemplate 保存数据】
    DevEco Studio鸿蒙虚拟机
    【c++】跟webrtc学std array 4: H264PacketBuffer 包缓存
    Go-Excelize API源码阅读(十六)——GetSheetViewOptions、SetPageLayout
    数字化转型中,企业设备管理会出现什么问题?JNPF或将是“最优解”
    07_面向对象高级_内部类
    推荐一款企业管理专用低代码工具,实现开发系统自由!
    2VGen-XL高清视频生成视频大模型
    kubelet源码分析-创建
  • 原文地址:https://blog.csdn.net/Jason6620/article/details/126114347