当前位置:   article > 正文

设计模式(三)

设计模式(三)

结构型模式

装饰器模式:

动态的给一个对象增加一些额外的职责,就增加功能来说,装饰模式比生成子类更为灵活。

优/缺点:装饰模式是继承关系的一个替代方案。装饰模式可以动态地扩展一个实现类的功能。缺点:多层的装饰还是比较复杂

何时使用:需要扩展一个类的功能,或给一个类增加附加功能;需要动态地给一个对象增加功能,这些功能可以再动态地撤销;需要为一批类进行改装或加装功能。

装饰模式是对继承的有力补充。单纯使用继承时,在一些情况下就会增加很多子类,而且灵活性差维护也不容易。装饰模式可以替代继承解决类膨胀的问题。

  1. #include <iostream>
  2. #include <string>
  3. #include <memory>
  4. class people
  5. {
  6. public:
  7. people() = default;
  8. explicit people(const std::string &name)
  9. : pname(name)
  10. { }
  11. virtual void show()const
  12. {
  13. std::cout << "装扮的" << pname << std::endl;
  14. }
  15. private:
  16. std::string pname;
  17. };
  18. class Finery : public people
  19. {
  20. public:
  21. void Decorate(std::shared_ptr<people> peo)
  22. {
  23. mpeople.swap(peo);
  24. }
  25. virtual void show()const override
  26. {
  27. if (mpeople != nullptr)
  28. {
  29. mpeople->show();
  30. }
  31. }
  32. private:
  33. std::shared_ptr<people> mpeople = nullptr;
  34. };
  35. class TShirts : public Finery
  36. {
  37. public:
  38. virtual void show()const override
  39. {
  40. std::cout << "穿大T恤 ";
  41. Finery::show();
  42. }
  43. };
  44. class Sneakers : public Finery
  45. {
  46. public:
  47. virtual void show()const override
  48. {
  49. std::cout << "穿着破球鞋 ";
  50. Finery::show();
  51. }
  52. };
  53. class Suit : public Finery
  54. {
  55. public:
  56. virtual void show()const override
  57. {
  58. std::cout << "穿西装 ";
  59. Finery::show();
  60. }
  61. };
  62. class LeatherShoes : public Finery
  63. {
  64. public:
  65. virtual void show()const override
  66. {
  67. std::cout << "穿皮鞋 ";
  68. Finery::show();
  69. }
  70. };
  71. int main()
  72. {
  73. std::shared_ptr<people> mp = std::make_shared<people>("小明");
  74. std::cout << "第一种装扮:\n";
  75. std::shared_ptr<Sneakers> sk = std::make_shared<Sneakers>();
  76. std::shared_ptr<TShirts> ts = std::make_shared<TShirts>();
  77. sk->Decorate(mp);
  78. ts->Decorate(sk);
  79. ts->show();
  80. std::cout << "第二种装扮:\n";
  81. std::shared_ptr<LeatherShoes> ls = std::make_shared<LeatherShoes>();
  82. std::shared_ptr<Suit> su = std::make_shared<Suit>();
  83. ls->Decorate(ts);
  84. su->Decorate(ls);
  85. su->show();
  86. return 0;
  87. }

代理模式: 

为其他对象提供一一种代理以控制这个对象的访问。曹操挟天子以令诸侯,在这里曹操就是被代理的人,而天子就是他的代理商。通过汉天子发出口号,但是实际上还是曹老板自己拿主意。

优点:使用代理模式创建代表对象,让代表对象来控制某对象的访问,被代理的对象可以是远程的对象,创建开销大的对象或需要安全控制的对象。

特点:职责清晰:真实的角色实现实际的业务逻辑,不用关心其它非本职的事务,通过后期的代理完成附加的事务,附带的结果就是编程简洁清晰。 高扩展性:具体主题角色随需求不同可能有很多种,但只要实现了接口,代理类就完全可以在不做任何修改的情况下代理各种真实主题角色。智能化:代理类可以在运行时才确定需要去代理的真实主题,这是一种强大的功能。

  1. #include <iostream>
  2. class Ordination
  3. {
  4. public:
  5. virtual ~Ordination() = default;
  6. virtual void command()const = 0;
  7. };
  8. class BossCao : public Ordination
  9. {
  10. public:
  11. virtual void command()const override
  12. {
  13. std::cout << "接天子命令攻打徐州捉拿刘备 " << std::endl;
  14. }
  15. };
  16. class emperorProxy : public Ordination
  17. {
  18. public:
  19. emperorProxy()
  20. {
  21. ep = new BossCao();
  22. }
  23. ~emperorProxy()
  24. {
  25. if (ep != nullptr)
  26. {
  27. delete ep;
  28. }
  29. }
  30. virtual void command()const override
  31. {
  32. std::cout << "我是天子请皇叔助阵 ";
  33. ep->command();
  34. }
  35. private:
  36. BossCao *ep = nullptr;
  37. };
  38. int main()
  39. {
  40. emperorProxy ep;
  41. ep.command();
  42. return 0;
  43. }

 外观模式:

为子系统的一组接口提供一个一致的界面,此模式定义一个高层接口,这一接口使得这一子系统更加容易使用。

  1. #include <iostream>
  2. using namespace std;
  3. class CAOstrategy
  4. {
  5. public:
  6. void strategy() const
  7. {
  8. cout << "宁负天下人 ";
  9. }
  10. };
  11. class CAOstrategy1
  12. {
  13. public:
  14. void strategy1() const
  15. {
  16. cout << " 挟天子令诸侯 "<<endl;
  17. }
  18. };
  19. class LIUstrategy
  20. {
  21. public:
  22. void strategy() const
  23. {
  24. cout << "仁";
  25. }
  26. };
  27. class LIUstrategy1
  28. {
  29. public:
  30. void strategy1() const
  31. {
  32. cout << " 义"<<endl;
  33. }
  34. };
  35. class SUNstrategy
  36. {
  37. public:
  38. void strategy() const
  39. {
  40. cout << "坚守";
  41. }
  42. };
  43. class Facade
  44. {
  45. public:
  46. void caoCaoFacade() const
  47. {
  48. cao.strategy();
  49. cao1.strategy1();
  50. }
  51. void LiubeiFacade() const
  52. {
  53. liu.strategy();
  54. bei.strategy1();
  55. }
  56. void sunQuanFacade() const
  57. {
  58. sunquan.strategy();
  59. }
  60. private:
  61. CAOstrategy cao;
  62. CAOstrategy1 cao1;
  63. LIUstrategy liu;
  64. LIUstrategy1 bei;
  65. SUNstrategy sunquan;
  66. };
  67. int main()
  68. {
  69. Facade fa;
  70. cout << "曹操的策略是 " ;
  71. fa.caoCaoFacade();
  72. cout << "刘备的策略是 ";
  73. fa.LiubeiFacade();
  74. cout << "孙权的策略是 ";
  75. fa.sunQuanFacade();
  76. return 0;
  77. }

优点:减少系统的相互依赖,所有的依赖都是对Façade对象的依赖(子系统的组合),与子系统无关。提高灵活性:不管子系统内部如何变化,只要不影响Facade对象,任何活动都是自由的。提高安全性: Facade中未提供的方法,外界就无法访问,提高系统的安全性。

缺点:是不符合开闭原则,对修改关闭,对扩展开放。

何时使用:为一个复杂的模块或子系统提供一个供外界访问的接口,子系统相对独立,外界对子系统的访问只要黑箱操作即可;预防风险扩散使用Façade进行访问操作控制。

适配器模式:

将一个类的接口变换成客户端期待的另一种接口,适配器让原本接口不兼容不能一起工作类一起工作。(通过创建适配器进行接口转换,让不兼容的接口变成兼容,可以让客户从实现的接口解耦(电压转换器))。

何时使用: 系统需要使用现有的类,而这些类的接口不符合系统的需要这是适配器模式就比较合适了;想要建立一个可以重复使用的类,用于与一些彼此之间没有太大关联的一些类一起工作;需要统一多个类的接口设计时;旧系统开发的类与新系统不一致时,可以使用适配器模式使得旧系统的功能同样能在新系统中使用。

  1. #include <iostream>
  2. using namespace std;
  3. class lvBu
  4. {
  5. public:
  6. virtual ~lvBu() = default;
  7. virtual void Request()const
  8. {
  9. cout << "杀董卓"<<endl;
  10. }
  11. };
  12. class LisuAdaptee
  13. {
  14. public:
  15. void SpecifiRequest()const
  16. {
  17. cout << "李肃游说献上赤兔马,吕布归顺 ";
  18. }
  19. };
  20. class Adapter : public lvBu
  21. {
  22. public:
  23. virtual void Request()const override
  24. {
  25. lisuAdp.SpecifiRequest();
  26. }
  27. private:
  28. LisuAdaptee lisuAdp;
  29. };
  30. int main()
  31. {
  32. lvBu *p = new Adapter();
  33. p->Request();
  34. delete p;
  35. p = nullptr;
  36. return 0;
  37. }

组合模式:

将对象组合成树形结构以表示“部分—整体”的层次结构,使得用户对单个对象和组合对象的使用具有一致性。

组合模式的优势:高层模块调用简单。一棵树形机构中的所有节点都是 Component,局部和整体对调用者来说没有任何区别,即高层模块不必关心自己处理的是单个对象还是整个组合结构,简化了高层模块的代码。另外节点自由增加。使用组合模式后,如果想增加一个树枝节点、树叶节点只需要找到其父节点即可。

模式的缺点:不易控制树枝构件的类型;不易使用继承的方法来增加新的行为。

何时使用:需求中有体现部分与整体结构,或者你希望客户可以忽略个体构件和组合构件的区别 ,统一使用组合结构中的所以对象。

  1. #include<iostream>
  2. #include <list>
  3. #include <memory>
  4. #include <stdio.h>
  5. #include <string>
  6. using namespace std;
  7. class Company {
  8. public:
  9. virtual string getInfo() = 0;
  10. virtual string getName()
  11. {
  12. return name;
  13. }
  14. virtual string getType() = 0;
  15. protected:
  16. string name;
  17. string position;
  18. };
  19. class ConcreteCompany :public Company {
  20. public:
  21. ConcreteCompany(string name, string position) {
  22. this->name = name;
  23. this->position = position;
  24. }
  25. void add(Company* company) {
  26. shared_ptr<Company> temp(company);
  27. companyList.push_back(temp);
  28. }
  29. string getType() {
  30. return "ConcreteCompany";
  31. }
  32. void remove(string companyName) {
  33. list<shared_ptr<Company>>::iterator iter = companyList.begin();
  34. for (; iter != companyList.end(); iter++)
  35. {
  36. if ((*iter).get()->getName() == companyName)
  37. {
  38. companyList.erase(iter);
  39. return;
  40. }
  41. }
  42. }
  43. list<shared_ptr<Company>> getChild() {
  44. return companyList;
  45. }
  46. string getInfo() {
  47. string info = "";
  48. info = "名称:" + this->name;
  49. info = info + "\t职位: " + this->position;
  50. return info;
  51. }
  52. private:
  53. list<shared_ptr<Company>> companyList;
  54. };
  55. class Employee :public Company {
  56. public:
  57. Employee(string name, string position) {
  58. this->name = name;
  59. this->position = position;
  60. }
  61. string getType() {
  62. return "Employee";
  63. }
  64. string getInfo() {
  65. string info = "";
  66. info = "名称:" + this->name;
  67. info = info + "\t职位: " + this->position;
  68. return info;
  69. }
  70. };
  71. void disPlay(ConcreteCompany* root) {
  72. cout << root->getInfo() << endl;
  73. list<shared_ptr<Company>> tmp = root->getChild();
  74. list<shared_ptr<Company>>::iterator iter = tmp.begin();
  75. for (; iter != tmp.end(); iter++)
  76. {
  77. if ((*iter).get()->getType() == string("Employee"))
  78. {
  79. cout << (*iter).get()->getInfo() << endl;
  80. }
  81. else {
  82. disPlay((ConcreteCompany*)(*iter).get());
  83. }
  84. }
  85. }
  86. int main() {
  87. ConcreteCompany* root = new ConcreteCompany("刘备", "汉中王");
  88. ConcreteCompany* develop = new ConcreteCompany("关羽", "荆州牧");
  89. ConcreteCompany* sale = new ConcreteCompany("关平", "少将军");
  90. Employee *e1 = new Employee("周仓", "副将");
  91. Employee *e2 = new Employee("廖化", "先锋");
  92. root->add(develop);
  93. root->add(sale);
  94. develop->add(e1);
  95. develop->add(e2);
  96. sale->add(e2);
  97. disPlay(root);
  98. cout<<"----"<<endl;
  99. develop->remove("周仓");
  100. disPlay(root);
  101. delete root;
  102. root = NULL;
  103. }

享元模式:

运用共享技术有效的有效地支持大量细粒度对象。类似于线程池,线程池可以避免不停的创建和销毁多个对象,消耗性能。

优点:享元模式的优点在于大幅减少内存中对象的数量,降低程序内存的占用,提高性能。缺点:使得系统更加复杂,为了使对象可以共享,需要将一些状态外部化,使得程序的逻辑复杂化;将享元对象的状态外部化,而读取外部状态使得运行时间稍微变长;

何时使用:系统中有大量的相似对象,这些对象耗费大量的内;细粒度的对象都具备较接近的外部状态,而且内部状态与环境无关,即对象没有特定身份;需要缓冲池的场景。

  1. #include <iostream>
  2. #include <unordered_set>
  3. using namespace std;
  4. // 抽象共享对象
  5. class FlyWeight {
  6. public:
  7. virtual ~FlyWeight() { };
  8. virtual void RideStata() = 0;//骑行状态
  9. virtual void ReturnBike() = 0;//归还自行车
  10. int getState() { //使用状态
  11. return state;
  12. }
  13. protected:
  14. int state = 0;
  15. };
  16. // 具体共享对象
  17. class BlueFlyWeight : public FlyWeight {
  18. public:
  19. BlueFlyWeight(string bikeId) : BikeId(bikeId) { }
  20. void RideStata() override {
  21. state = 1;
  22. cout << BikeId << "号自行车被骑行中..." << endl;
  23. }
  24. void ReturnBike() override {
  25. state = 0;
  26. }
  27. private:
  28. string BikeId;
  29. };
  30. // 共享对象的建造工厂
  31. class BikeFlyWeightFactory {
  32. public:
  33. ~BikeFlyWeightFactory() {
  34. delete instance;
  35. for (auto& bike : pool) {
  36. delete bike;
  37. }
  38. }
  39. static BikeFlyWeightFactory* getInstance() {
  40. return instance;
  41. }
  42. FlyWeight* getBike() {
  43. for (const auto& bike : pool) {
  44. if (bike->getState() == 0) {
  45. return bike;
  46. }
  47. }
  48. return nullptr;
  49. }
  50. private:
  51. BikeFlyWeightFactory() {
  52. for (int i = 0; i < 2; ++i) {
  53. pool.insert(new BlueFlyWeight(to_string(i)));
  54. }
  55. }
  56. BikeFlyWeightFactory(const BikeFlyWeightFactory&) = delete;
  57. BikeFlyWeightFactory(const BikeFlyWeightFactory&&) = delete;
  58. BikeFlyWeightFactory& operator=(const BikeFlyWeightFactory&) = delete;
  59. BikeFlyWeightFactory& operator=(const BikeFlyWeightFactory&&) = delete;
  60. static BikeFlyWeightFactory *instance;
  61. unordered_set<FlyWeight*> pool;
  62. };
  63. BikeFlyWeightFactory* BikeFlyWeightFactory::instance = new BikeFlyWeightFactory();
  64. int main() {
  65. FlyWeight* bike1 = BikeFlyWeightFactory::getInstance()->getBike();
  66. bike1->RideStata();
  67. FlyWeight* bike2 = BikeFlyWeightFactory::getInstance()->getBike();
  68. bike2->RideStata();
  69. bike2->ReturnBike();//归还自行车
  70. FlyWeight* bike3 = BikeFlyWeightFactory::getInstance()->getBike();
  71. bike3->RideStata(); //归还的车可以复用不用再造新车
  72. cout<<(bike1==bike2?"same":"notsame")<<endl;//notsame
  73. cout<<(bike2==bike3?"same":"notsame")<<endl;//same
  74. }

桥接模式:

将抽象部分与它的实现部分离,使它们都可以独立的变化。

  1. #include <iostream>
  2. // 实现类接口(Implementor)
  3. class DrawingAPI {
  4. public:
  5. virtual void drawCircle(float x, float y, float radius) = 0;
  6. };
  7. // 具体实现类(ConcreteImplementor)
  8. class DrawingAPI1 : public DrawingAPI {
  9. public:
  10. void drawCircle(float x, float y, float radius) override {
  11. std::cout << "API1: Drawing Circle at (" << x << ", " << y << ") with radius " << radius << std::endl;
  12. }
  13. };
  14. // 具体实现类(ConcreteImplementor)
  15. class DrawingAPI2 : public DrawingAPI {
  16. public:
  17. void drawCircle(float x, float y, float radius) override {
  18. std::cout << "API2: Drawing Circle at (" << x << ", " << y << ") with radius " << radius << std::endl;
  19. }
  20. };
  21. // 抽象类(Abstraction)
  22. class CircleShape {
  23. protected:
  24. DrawingAPI* drawingAPI;
  25. public:
  26. CircleShape(DrawingAPI* api) : drawingAPI(api) {}
  27. virtual void draw() = 0;
  28. virtual ~CircleShape() {}
  29. };
  30. // 具体类(RefinedAbstraction)
  31. class Circle : public CircleShape {
  32. private:
  33. float x, y, radius;
  34. public:
  35. Circle(DrawingAPI* api, float x, float y, float radius) : CircleShape(api), x(x), y(y), radius(radius) {}
  36. void draw() override {
  37. drawingAPI->drawCircle(x, y, radius);
  38. }
  39. };
  40. int main() {
  41. DrawingAPI1 api1;
  42. DrawingAPI2 api2;
  43. CircleShape* shape1 = new Circle(&api1, 10, 10, 10);
  44. CircleShape* shape2 = new Circle(&api2, 20, 20, 20);
  45. shape1->draw();
  46. shape2->draw();
  47. delete shape1;
  48. delete shape2;
  49. return 0;
  50. }

 CircleShape 类作为抽象类,它维护了一个指向实现类接口(DrawingAPI)的指针。Circle 是具体的实现类,它实现了抽象类的方法,并使用实现类接口来完成绘制工作,测试函数中创建了两个具体的实现类对象和两个使用这些实现类的圆形对象,并调用它们的绘制方法。这样,通过更改实现类对象,可以在不修改Circle 类的情况下改变绘制行为。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/正经夜光杯/article/detail/1022390
推荐阅读
相关标签
  

闽ICP备14008679号