当前位置: 首页 > news >正文

设计模式(三)

结构型模式

装饰器模式:

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

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

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

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

#include <iostream>
#include <string>
#include <memory>
class people
{
public:people() = default;explicit people(const std::string &name): pname(name){	}virtual void show()const{std::cout << "装扮的" << pname << std::endl;}
private:std::string pname;
};class Finery : public people
{
public:void Decorate(std::shared_ptr<people> peo){mpeople.swap(peo);}virtual void show()const override{if (mpeople != nullptr){mpeople->show();}}
private:std::shared_ptr<people> mpeople = nullptr;
};class TShirts : public Finery
{
public:virtual void show()const override {std::cout << "穿大T恤 ";Finery::show();}
};class Sneakers : public Finery
{
public:virtual void show()const override{std::cout << "穿着破球鞋 ";Finery::show();}
};class Suit : public Finery
{
public:virtual void show()const override{std::cout << "穿西装 ";Finery::show();}
};class LeatherShoes : public Finery
{
public:virtual void show()const override{std::cout << "穿皮鞋 ";Finery::show();}
};int main()
{std::shared_ptr<people> mp = std::make_shared<people>("小明");std::cout << "第一种装扮:\n";std::shared_ptr<Sneakers> sk = std::make_shared<Sneakers>();std::shared_ptr<TShirts> ts = std::make_shared<TShirts>();sk->Decorate(mp);ts->Decorate(sk);ts->show();std::cout << "第二种装扮:\n";std::shared_ptr<LeatherShoes> ls = std::make_shared<LeatherShoes>();std::shared_ptr<Suit> su = std::make_shared<Suit>();ls->Decorate(ts);su->Decorate(ls);su->show();return 0;
}

代理模式: 

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

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

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

#include <iostream>class Ordination
{
public:virtual ~Ordination() = default;virtual void command()const = 0;
};
class BossCao : public Ordination
{
public:virtual void command()const override{std::cout << "接天子命令攻打徐州捉拿刘备 " << std::endl;}
};
class emperorProxy : public Ordination
{
public:emperorProxy(){ep = new BossCao();}~emperorProxy(){if (ep != nullptr){delete ep;}}virtual void command()const override{std::cout << "我是天子请皇叔助阵 ";ep->command();}
private:BossCao *ep = nullptr;
};
int main()
{emperorProxy ep;ep.command();return 0;
}

 外观模式:

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

#include <iostream>
using namespace std;
class CAOstrategy
{
public:void strategy() const{cout << "宁负天下人 ";}
};class CAOstrategy1
{
public:void strategy1() const{cout << " 挟天子令诸侯 "<<endl;}
};class LIUstrategy
{
public:void strategy() const{cout << "仁";}
};class LIUstrategy1
{
public:void strategy1() const{cout << " 义"<<endl;}
};class SUNstrategy
{
public:void strategy() const{cout << "坚守";}
};class Facade
{
public:void caoCaoFacade() const{cao.strategy();cao1.strategy1();}void LiubeiFacade() const{liu.strategy();bei.strategy1();}void sunQuanFacade() const{sunquan.strategy();}private:CAOstrategy cao;CAOstrategy1 cao1;LIUstrategy liu;LIUstrategy1 bei;SUNstrategy sunquan;
};
int main()
{Facade fa;cout << "曹操的策略是 " ;fa.caoCaoFacade();cout << "刘备的策略是 ";fa.LiubeiFacade();cout << "孙权的策略是 ";fa.sunQuanFacade();return 0;
}

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

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

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

适配器模式:

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

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

#include <iostream>
using namespace std;
class lvBu
{
public:virtual ~lvBu() = default;virtual void Request()const{cout << "杀董卓"<<endl;}
};class LisuAdaptee
{
public:void SpecifiRequest()const{cout << "李肃游说献上赤兔马,吕布归顺 ";}
};class Adapter : public lvBu
{
public:virtual void Request()const override{lisuAdp.SpecifiRequest();}
private:LisuAdaptee lisuAdp;
};int main()
{lvBu *p = new Adapter();p->Request();delete p;p = nullptr;return 0;
}

组合模式:

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

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

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

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

#include<iostream>
#include <list>
#include <memory>
#include <stdio.h>
#include <string>
using namespace std;
class Company {
public:virtual string getInfo() = 0;virtual  string getName(){return name;}virtual string getType() = 0;
protected:string name;string position;
};
class ConcreteCompany :public Company {
public:ConcreteCompany(string name, string position) {this->name = name;this->position = position;}void add(Company* company) {shared_ptr<Company> temp(company);companyList.push_back(temp);}string getType() {return "ConcreteCompany";}void remove(string companyName) {list<shared_ptr<Company>>::iterator iter = companyList.begin();for (; iter != companyList.end(); iter++){if ((*iter).get()->getName() == companyName){companyList.erase(iter);return;}}}list<shared_ptr<Company>> getChild() {return companyList;}string getInfo() {string info = "";info = "名称:" + this->name;info = info + "\t职位: " + this->position;return info;}
private:list<shared_ptr<Company>> companyList;
};class Employee :public Company {
public:Employee(string name, string position) {this->name = name;this->position = position;}string getType() {return "Employee";}string getInfo() {string info = "";info = "名称:" + this->name;info = info + "\t职位: " + this->position;return info;}
};
void disPlay(ConcreteCompany* root) {cout << root->getInfo() << endl;list<shared_ptr<Company>> tmp = root->getChild();list<shared_ptr<Company>>::iterator iter = tmp.begin();for (; iter != tmp.end(); iter++){if ((*iter).get()->getType() == string("Employee")){cout << (*iter).get()->getInfo() << endl;}else {disPlay((ConcreteCompany*)(*iter).get());}}}
int main() {ConcreteCompany* root = new ConcreteCompany("刘备", "汉中王");ConcreteCompany* develop = new ConcreteCompany("关羽", "荆州牧");ConcreteCompany* sale = new ConcreteCompany("关平", "少将军");Employee *e1 = new Employee("周仓", "副将");Employee *e2 = new Employee("廖化", "先锋");root->add(develop);root->add(sale);develop->add(e1);develop->add(e2);sale->add(e2);disPlay(root);cout<<"----"<<endl;develop->remove("周仓");disPlay(root);delete root;root = NULL;}

享元模式:

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

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

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

#include <iostream>
#include <unordered_set>
using namespace std;// 抽象共享对象
class FlyWeight {
public:virtual ~FlyWeight() { };virtual void RideStata() = 0;//骑行状态virtual void ReturnBike() = 0;//归还自行车int getState() { //使用状态return state;}
protected:int state = 0; 
};// 具体共享对象
class BlueFlyWeight : public FlyWeight {
public:BlueFlyWeight(string bikeId) : BikeId(bikeId) { }void RideStata() override {state = 1;cout << BikeId << "号自行车被骑行中..." << endl;}void ReturnBike() override {state = 0;}
private:string BikeId;
};// 共享对象的建造工厂
class BikeFlyWeightFactory {
public:~BikeFlyWeightFactory() {delete instance;for (auto& bike : pool) {delete bike;}}static BikeFlyWeightFactory* getInstance() {return instance;}FlyWeight* getBike() {for (const auto& bike : pool) {if (bike->getState() == 0) {return bike;}}return nullptr;}
private:BikeFlyWeightFactory() {for (int i = 0; i < 2; ++i) {pool.insert(new BlueFlyWeight(to_string(i)));}}BikeFlyWeightFactory(const BikeFlyWeightFactory&) = delete;BikeFlyWeightFactory(const BikeFlyWeightFactory&&) = delete;BikeFlyWeightFactory& operator=(const BikeFlyWeightFactory&) = delete;BikeFlyWeightFactory& operator=(const BikeFlyWeightFactory&&) = delete;static BikeFlyWeightFactory *instance;unordered_set<FlyWeight*> pool; 
};BikeFlyWeightFactory* BikeFlyWeightFactory::instance = new BikeFlyWeightFactory();int main() {FlyWeight* bike1 = BikeFlyWeightFactory::getInstance()->getBike();bike1->RideStata();FlyWeight* bike2 = BikeFlyWeightFactory::getInstance()->getBike();bike2->RideStata();bike2->ReturnBike();//归还自行车FlyWeight* bike3 = BikeFlyWeightFactory::getInstance()->getBike();bike3->RideStata(); //归还的车可以复用不用再造新车cout<<(bike1==bike2?"same":"notsame")<<endl;//notsamecout<<(bike2==bike3?"same":"notsame")<<endl;//same
}

桥接模式:

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

#include <iostream>// 实现类接口(Implementor)
class DrawingAPI {
public:virtual void drawCircle(float x, float y, float radius) = 0;
};// 具体实现类(ConcreteImplementor)
class DrawingAPI1 : public DrawingAPI {
public:void drawCircle(float x, float y, float radius) override {std::cout << "API1: Drawing Circle at (" << x << ", " << y << ") with radius " << radius << std::endl;}
};// 具体实现类(ConcreteImplementor)
class DrawingAPI2 : public DrawingAPI {
public:void drawCircle(float x, float y, float radius) override {std::cout << "API2: Drawing Circle at (" << x << ", " << y << ") with radius " << radius << std::endl;}
};// 抽象类(Abstraction)
class CircleShape {
protected:DrawingAPI* drawingAPI;public:CircleShape(DrawingAPI* api) : drawingAPI(api) {}virtual void draw() = 0;virtual ~CircleShape() {}
};// 具体类(RefinedAbstraction)
class Circle : public CircleShape {
private:float x, y, radius;public:Circle(DrawingAPI* api, float x, float y, float radius) : CircleShape(api), x(x), y(y), radius(radius) {}void draw() override {drawingAPI->drawCircle(x, y, radius);}
};int main() {DrawingAPI1 api1;DrawingAPI2 api2;CircleShape* shape1 = new Circle(&api1, 10, 10, 10);CircleShape* shape2 = new Circle(&api2, 20, 20, 20);shape1->draw();shape2->draw();delete shape1;delete shape2;return 0;
}

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

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • ctfshow之web29~web51
  • 编译运行 llama.cpp (vulkan, Intel GPU SYCL)
  • 【数学分析笔记】第2章第4节收敛准则(1)
  • ES之二:centos7安装kibana和IK分词器
  • React的生命周期方法以及React 18之后的变化
  • 时序预测|基于贝叶斯BO-卷积-双向门控单元-注意力机制的单变量时间序列预测模型BO-CNN-BiGRU-Attention
  • SMF05C.TCT TVS二极管阵列用于ESD和锁定保护芯片IC
  • github源码指引:C++嵌入式WEB服务器
  • JAVA面试题--ES
  • 切面条(蓝桥杯-基础)
  • 【通信协议】SPI总线
  • JVM - 1.类加载子系统
  • 工业相机错峰启动优化方案
  • 【最长公共子序列】
  • 程序员的日常挑战:如何在编码工作与持续学习之间找到平衡?
  • ComponentOne 2017 V2版本正式发布
  • CSS 专业技巧
  • EOS是什么
  • JavaScript设计模式系列一:工厂模式
  • java小心机(3)| 浅析finalize()
  • js正则,这点儿就够用了
  • Redash本地开发环境搭建
  • Redux 中间件分析
  • win10下安装mysql5.7
  • 分享一个自己写的基于canvas的原生js图片爆炸插件
  • 前端学习笔记之观察者模式
  • 如何解决微信端直接跳WAP端
  • 消息队列系列二(IOT中消息队列的应用)
  • 再次简单明了总结flex布局,一看就懂...
  • 看到一个关于网页设计的文章分享过来!大家看看!
  • 【运维趟坑回忆录 开篇】初入初创, 一脸懵
  • 资深实践篇 | 基于Kubernetes 1.61的Kubernetes Scheduler 调度详解 ...
  • ​插件化DPI在商用WIFI中的价值
  • (C语言)逆序输出字符串
  • (html转换)StringEscapeUtils类的转义与反转义方法
  • (k8s中)docker netty OOM问题记录
  • (二)Kafka离线安装 - Zookeeper下载及安装
  • (翻译)Entity Framework技巧系列之七 - Tip 26 – 28
  • (附源码)springboot 房产中介系统 毕业设计 312341
  • (规划)24届春招和25届暑假实习路线准备规划
  • (佳作)两轮平衡小车(原理图、PCB、程序源码、BOM等)
  • (亲测)设​置​m​y​e​c​l​i​p​s​e​打​开​默​认​工​作​空​间...
  • (一)、软硬件全开源智能手表,与手机互联,标配多表盘,功能丰富(ZSWatch-Zephyr)
  • (一)Linux+Windows下安装ffmpeg
  • (原創) 如何動態建立二維陣列(多維陣列)? (.NET) (C#)
  • (转)JAVA中的堆栈
  • (转)Sql Server 保留几位小数的两种做法
  • .NET C# 操作Neo4j图数据库
  • .net 打包工具_pyinstaller打包的exe太大?你需要站在巨人的肩膀上-VC++才是王道
  • .NET 给NuGet包添加Readme
  • .NET 使用 JustAssembly 比较两个不同版本程序集的 API 变化
  • .NET/C# 项目如何优雅地设置条件编译符号?
  • .NET开源的一个小而快并且功能强大的 Windows 动态桌面软件 - DreamScene2
  • .NET轻量级ORM组件Dapper葵花宝典
  • .NET是什么