首页 文章 精选 留言 我的

精选列表

搜索[c 17],共10000篇文章
优秀的个人博客,低调大师

C++桥接模式

简述 桥接模式(Bridge Pattern)是将抽象部分与它的实现部分分离,使它们都可以独立地变化。 简述 模式结构 优缺点 适用场景 案例分析 代码实现 版权所有:一去丶二三里,转载请注明出处:http://blog.csdn.net/liang19890820 模式结构 UML 结构图: Abstraction(抽象类):用于定义抽象类的接口,并且维护一个指向 Implementor 实现类的指针。它与 Implementor 之间具有关联关系。 RefinedAbstraction(扩充抽象类):扩充由 Abstraction 定义的接口,在 RefinedAbstraction 中可以调用在 Implementor 中定义的业务方法。 Implementor(实现类接口):定义实现类的接口,这个接口不一定要与 Abstraction 的接口完全一致,事实上这两个接口可以完全不同。 ConcreteImplementor(具体实现类):实现了 Implementor 定义的接口,在不同的 ConcreteImplementor 中提供基本操作的不同实现。在程序运行时,ConcreteImplementor 对象将替换其父类对象,提供给 Abstraction 具体的业务操作方法。 优缺点 优点: 分离抽象和实现部分。桥接模式使用“对象间的关联关系”解耦了抽象和实现之间固有的绑定关系,使得抽象和实现可以沿着各自的维度来变化。所谓抽象和实现沿着各自维度的变化,也就是说抽象和实现不再在同一个继承层次结构中,而是“子类化”它们,使它们各自都具有自己的子类,以便任何组合子类,从而获得多维度组合对象。 在很多情况下,桥接模式可以取代多层继承方案,多层继承方案违背了“单一职责原则”,复用性较差,且类的个数非常多,桥接模式是比多层继承方案更好的解决方法,它极大减少了子类的个数。 桥接模式提高了系统的可扩展性,在两个变化维度中任意扩展一个维度,都不需要修改原有系统,符合“开闭原则”。 缺点: 桥接模式的使用会增加系统的理解与设计难度,由于关联关系建立在抽象层,要求开发者一开始就针对抽象层进行设计与编程。 桥接模式要求正确识别出系统中两个独立变化的维度,因此其使用范围具有一定的局限性,如何正确识别两个独立维度也需要一定的经验积累。 适用场景 如果一个系统需要在抽象化和具体化之间增加更多的灵活性,避免在两个层次之间建立静态的继承关系,通过桥接模式可以使它们在抽象层建立一个关联关系。 “抽象部分”和“实现部分”可以以继承的方式独立扩展而互不影响,在程序运行时可以动态将一个抽象化子类的对象和一个实现化子类的对象进行组合,即系统需要对抽象化角色和实现化角色进行动态耦合。 一个系统存在多个(≥ 2)独立变化的维度,且这多个维度都需要独立进行扩展。 对于那些不希望使用继承或因为多层继承导致系统类的个数急剧增加的系统,桥接模式尤为适用。 案例分析 开关和电器 电器是现代生活必不可少的东西,几乎每家每户都有,电视、风扇、电灯。。。无论什么电器,都由开关控制。开关种类众多,有拉链式开关、两位开关、调光开关。。。 不管任何时候,都可以在不触及其它东西的情况下更换设备。例如,可以在不更换开关的情况下换掉灯泡,也可以在不接触灯泡或风扇的情况下更换开关,甚至可以在不接触开关的情况下将灯泡和风扇互换。 这看起来很自然,当然也应该这样!当不同的事物联系到一起时,它们应该在一个可以变更或者替换的系统中,以便不相互影响或者影响尽可能的小,这样才能更方便、更低成本地去管理系统。想象一下,如果要换房间里的一个灯泡,得要求把开关也换了,你会考虑使用这样的系统吗? 代码实现 创建实现类接口 所有电器都有一些共性,可以被打开和关闭: // implementor.h #ifndef IMPLEMENTOR_H #define IMPLEMENTOR_H // 电器 class IElectricalEquipment { public: virtual ~IElectricalEquipment() {} // 打开 virtual void PowerOn() = 0; // 关闭 virtual void PowerOff() = 0; }; #endif // IMPLEMENTOR_H 创建具体实现类 接下来,是真正的电器 - 电灯和风扇,它们实现了 IElectricalEquipment 接口: // concrete_implementor.h #ifndef CONCRETE_IMPLEMENTOR_H #define CONCRETE_IMPLEMENTOR_H #include "implementor.h" #include <iostream> // 电灯 class Light : public IElectricalEquipment { public: // 开灯 virtual void PowerOn() override { std::cout << "Light is on." << std::endl; } // 关灯 virtual void PowerOff() override { std::cout << "Light is off." << std::endl; } }; // 风扇 class Fan : public IElectricalEquipment { public: // 打开风扇 virtual void PowerOn() override { std::cout << "Fan is on." << std::endl; } // 关闭风扇 virtual void PowerOff() override { std::cout << "Fan is off." << std::endl; } }; #endif // CONCRETE_IMPLEMENTOR_H 创建抽象类 对于开关来说,它并不知道电灯和风扇的存在,只知道自己可以控制(打开/关闭)某个电器。也就是说,每个 ISwitch 应该持有一个 IElectricalEquipment 对象: // abstraction.h #ifndef ABSTRACTION_H #define ABSTRACTION_H #include "implementor.h" // 开关 class ISwitch { public: ISwitch(IElectricalEquipment *ee) { m_pEe = ee;} virtual ~ISwitch() {} // 打开电器 virtual void On() = 0; // 关闭电器 virtual void Off() = 0; protected: IElectricalEquipment *m_pEe; }; #endif // ABSTRACTION_H 创建扩充抽象类 特定类型的开关很多,比如拉链式开关、两位开关: // refined_abstraction.h #ifndef REFINED_ABSTRACTION_H #define REFINED_ABSTRACTION_H #include "abstraction.h" #include <iostream> // 拉链式开关 class PullChainSwitch : public ISwitch { public: PullChainSwitch(IElectricalEquipment *ee) : ISwitch(ee) {} // 用拉链式开关打开电器 virtual void On() override { std::cout << "Switch on the equipment with a pull chain switch." << std::endl; m_pEe->PowerOn(); } // 用拉链式开关关闭电器 virtual void Off() override { std::cout << "Switch off the equipment with a pull chain switch." << std::endl; m_pEe->PowerOff(); } }; // 两位开关 class TwoPositionSwitch : public ISwitch { public: TwoPositionSwitch(IElectricalEquipment *ee) : ISwitch(ee) {} // 用两位开关打开电器 virtual void On() override { std::cout << "Switch on the equipment with a two-position switch." << std::endl; m_pEe->PowerOn(); } // 用两位开关关闭电器 virtual void Off() override { std::cout << "Switch off the equipment with a two-position switch." << std::endl; m_pEe->PowerOff(); } }; #endif // REFINED_ABSTRACTION_H 创建客户端 很好,是时候将开关和电器关联起来了: // main.cpp #include "refined_abstraction.h" #include "concrete_implementor.h" #ifndef SAFE_DELETE #define SAFE_DELETE(p) { if(p){delete(p); (p)=NULL;} } #endif int main() { // 创建电器 - 电灯、风扇 IElectricalEquipment *light = new Light(); IElectricalEquipment *fan = new Fan(); /** * 创建开关 - 拉链式开关、两位开关 * 将拉链式开关和电灯关联起来,将两位开关和风扇关联起来 **/ ISwitch *pullChain = new PullChainSwitch(light); ISwitch *twoPosition= new TwoPositionSwitch(fan); // 开灯、关灯 pullChain->On(); pullChain->Off(); // 打开风扇、关闭风扇 twoPosition->On(); twoPosition->Off(); SAFE_DELETE(twoPosition); SAFE_DELETE(pullChain); SAFE_DELETE(fan); SAFE_DELETE(light); getchar(); return 0; } 输出如下: Switch on the equipment with a pull chain switch. Light is on. Switch off the equipment with a pull chain switch. Light is off. Switch on the equipment with a two-position switch. Fan is on. Switch off the equipment with a two-position switch. Fan is off.

优秀的个人博客,低调大师

C++模版方法模式

简述 模版方法模式(Template Method Pattern)定义一个操作中算法的骨架,而将一些步骤延迟到子类中。模板方法使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。 简述 模式结构 优缺点 适用场景 案例分析 代码实现 版权所有:一去丶二三里,转载请注明出处:http://blog.csdn.net/liang19890820 模式结构 UML 结构图: 抽象类(AbstractClass):定义抽象的原语操作,具体的子类将重定义它们以实现一个算法的各步骤。主要是实现一个模板方法,定义一个算法的骨架。该模板方法不仅调用原语操作,也调用定义在 AbstractClass 或其他对象中的操作。 具体类(ConcreteClass):实现原语操作以完成算法中与特定子类相关的步骤。 优缺点 优点: 在父类中形式化地定义一个算法,而由其子类实现细节的处理,在子类实现详细的处理算法时并不会改变算法中步骤的执行次序。 模板方法模式是一种代码复用技术,在类库设计中尤为重要,它提取了类库中的公共行为,将公共行为放在父类中,而通过其子类来实现不同的行为,它鼓励我们恰当使用继承来实现代码复用。 可实现一种反向控制结构,通过子类覆盖父类的钩子方法来决定某一特定步骤是否需要执行。 在模板方法模式中,可以通过子类来覆盖父类的基本方法,不同的子类可以提供基本方法的不同实现,更换和增加新的子类很方便,符合单一职责原则和开闭原则。 缺点: 需要为每一个基本方法的不同实现提供一个子类,如果父类中可变的基本方法太多,将会导致类的个数增加,系统更加庞大,设计也更加抽象,此时,可结合桥接模式来进行设计。 适用场景 对一些复杂的算法进行分割,将算法中固定不变的部分设计为模板方法和父类具体方法,而一些可变的细节由子类实现。 各子类中公共的行为应被提取出来并集中到一个公共父类中,以避免代码重复。 需要通过子类来决定父类算法中某个步骤是否执行,实现子类对父类的反向控制。 案例分析 招聘流程 谈及校招,对学生们而言,最诱人的名字无疑是 BAT,工资高、福利好,而且还能学到很多前沿的技术!当然,巨头公司的 Offer 不是那么容易拿的,不仅要成绩优异,更要技术过人。 无论什么公司,在校招时一般都会采用“宣讲会 -> 接收简历 -> 面试 -> 发放 Offer”这样一套固定流程。其中,各公司宣讲会(宣传企业文化、福利待遇)和接收简历(自带简历)的形式几乎是一样的,不同的是面试和发放 Offer 环节。阿里需要经过一面、二面、三面,并提供30W/年的薪酬;而腾讯则需要一面、二面,并提供25W/年的薪酬。 这里,公司是抽象类,“宣讲会 -> 接收简历 -> 面试 -> 发放 Offer”则是一套固定的模板方法(招聘流程)。具体类由阿里和腾讯表示,不同之处在于面试和发放 Offer 环节,需要它们分别实现。 代码实现 创建抽象类 抽象类由 Company 表示,它提供了一套固定的模板方法 Recruit(),用于标准化算法的骨架: // abstract_class.h #ifndef ABSTRACT_CLASS_H #define ABSTRACT_CLASS_H #include <iostream> // 公司 class Company { public: virtual ~Company() {} // 校园招聘 void Recruit() { std::cout << "---------- Begin ----------" << std::endl; CareerTalk(); ReceiveResume(); Interview(); Offer(); std::cout << "---------- End ----------" << std::endl; } // 宣讲会 void CareerTalk() { std::cout << "Delivery" << std::endl; } // 接收简历 void ReceiveResume() { std::cout << "Receive Resume" << std::endl; } // 面试 virtual void Interview() = 0; // 发放 Offer virtual void Offer() = 0; }; #endif // ABSTRACT_CLASS_H 注意: 相同的行为 CareerTalk() 和 ReceiveResume() 有默认实现,不同的行为 Interview() 和 Offer() 采用“占位符”方式,需要由具体公司来实现。 创建具体类 具体公司有两个 - Alibaba、Tencent,它们的面试、录用方式不同: // concrete_class.h #ifndef CONCRETE_CLASS_H #define CONCRETE_CLASS_H #include "abstract_class.h" #include <iostream> // 阿里 class Alibaba : public Company { public: virtual void Interview() override { std::cout << "First interview -> Second interview -> Third interview" << std::endl; } virtual void Offer() override { std::cout << "30W" << std::endl; } }; // 腾讯 class Tencent : public Company { public: virtual void Interview() override { std::cout << "First interview -> Second interview" << std::endl; } virtual void Offer() override { std::cout << "25W" << std::endl; } }; #endif // CONCRETE_CLASS_H 创建客户端 校招开启,Offer 快到碗里来: // main.cpp #include "concrete_class.h" #ifndef SAFE_DELETE #define SAFE_DELETE(p) { if(p){delete(p); (p)=NULL;} } #endif int main() { // 阿里校招 Company *alibaba = new Alibaba(); alibaba->Recruit(); // 腾讯校招 Company *tencent = new Tencent(); tencent->Recruit(); SAFE_DELETE(tencent); SAFE_DELETE(alibaba); getchar(); return 0; } 输出如下: ———- Begin ———- Delivery Receive Resume First interview -> Second interview -> Third interview 30W ———- End ———- ———- Begin ———- Delivery Receive Resume First interview -> Second interview 25W ———- End ———-

优秀的个人博客,低调大师

C++职责链模式

简述 职责链模式(Chain of Responsibility Pattern)使多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系。将这些对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理它为止。 简述 模式结构 优缺点 适用场景 案例分析 代码实现 版权所有:一去丶二三里,转载请注明出处:http://blog.csdn.net/liang19890820 模式结构 UML 结构图: Handler(抽象处理者):定义了处理请求所需的接口。 ConcreteHandler(具体处理者):处理自己负责的请求,如果无法处理,则将请求传递给与之保持联系的后继者(即:successor)。 Client(客户端):请求的发起者,将访问 Handler 来处理它。 优缺点 优点: 降低耦合度,将请求的发送者和接收者解耦。 简化了对象,使得对象不需要知道链的结构。 增强给对象指派职责的灵活性,通过改变链内的成员或者调整它们的次序来动态改变职责。 增加新的具体处理者很方便,无须修改原有代码,只需要在客户端重新建链即可。 缺点: 由于没有明确的接收者,所以无法保证请求一定会被处理(可能直到链的末端都得不到处理,也可能因为链没有配置正确而得不到处理。) 对于较长的职责链来说,请求可能涉及到多个处理对象,这将会使系统性能受到一定影响,而且不利于代码调试。 如果建链不当,可能会造成循环调用,这将导致系统陷入死循环。 适用场景 有多个对象可以处理同一请求,具体哪个对象处理由运行时刻自动确定。客户端只负责提交请求,而无须关心请求的处理对象是谁以及它是如何处理的。 在不明确指定接受者的情况下,向多个对象中的一个提交一个请求。 可动态指定一组对象处理请求,客户端可以动态创建职责链来处理请求,还可以改变链中处理者之间的先后次序。 案例分析 请假 - 流程处理 混迹职场,从来都身不由己,谁不想在繁忙的工作里偷得浮生半日闲。但请假从来都是一门技术活,拼技术,更拼情商! 无论如何,只要你愿意,从感冒到被绑架,一定能找出一万种理由: 自我诅咒版:感冒、发烧、肠胃炎 … 俗套肥皂剧:飞机延误、火车晚点、家里遭窃 … 大打感情牌:看望父母、失恋了 … 积劳成疾可怜版:工作压力太大、加班累坏了 … 无需理由的理由:老板,我是不是有 5 天年假? 彪悍的人生不需要解释,如果没有过这种请假经历,就不是职场老司机。。。 当员工发出请假请求时,链中的处理者可以对请求作出响应或者将其传递给上级。每个处理者都有自己的一套规则,而这套规则是他们可以批准的。审批流程:经理(1 天及以下) -> 总监(3 天及以下) -> 总裁(7 天为界限)。 代码实现 创建抽象处理者 抽象处理者除了提供一个处理请假的接口之外,还有一个很关键的地方就是定义后继者,这样便可以构建一条链: // handler.h #ifndef HANDLER_H #define HANDLER_H #include <iostream> // 抽象处理者 class IHandler { public: IHandler() { m_pSuccessor = NULL; } virtual ~IHandler() {} void SetSuccessor(IHandler *successor) { m_pSuccessor = successor; } virtual void HandleRequest(float days) = 0; protected: IHandler *m_pSuccessor; // 后继者 }; #endif // HANDLER_H 创建具体处理者 具体处理者包含 Manager、Director、CEO,它们的实现基本相同,只是批准的天数不一样: // concrete_handler.h #ifndef CONCRETE_HANDLER_H #define CONCRETE_HANDLER_H #include "handler.h" // 经理 class Manager : public IHandler { public: Manager() {} ~Manager() {} virtual void HandleRequest(float days) override { if (days <= 1) { std::cout << "Manager 批准了 " << days << " 天假" << std::endl; } else { m_pSuccessor->HandleRequest(days); } } }; // 总监 class Director : public IHandler { public: Director() {} ~Director() {} virtual void HandleRequest(float days) override { if (days <= 3) { std::cout << "Director 批准了 " << days << " 天假" << std::endl; } else { m_pSuccessor->HandleRequest(days); } } }; // 总裁 class CEO : public IHandler { public: CEO() {} ~CEO() {} virtual void HandleRequest(float days) override { if (days <= 7) { std::cout << "CEO 批准了 " << days << " 天假" << std::endl; } else { std::cout << "给你放长假,以后不用来上班啦!" << std::endl; } } }; #endif // CONCRETE_HANDLER_H 注意: 由于 CEO 位于最高层(处于链的末尾),所以请求到此结束,不会继续向下传递。 创建客户端 开始请假,说出你的理由: // main.cpp #include "concrete_handler.h" #ifndef SAFE_DELETE #define SAFE_DELETE(p) { if(p){delete(p); (p)=NULL;} } #endif int main() { IHandler *manager = new Manager(); IHandler *director = new Director(); IHandler *ceo = new CEO(); // 职责链:经理 -> 总监 -> 总裁 manager->SetSuccessor(director); director->SetSuccessor(ceo); manager->HandleRequest(1); manager->HandleRequest(2); manager->HandleRequest(5); manager->HandleRequest(10); SAFE_DELETE(manager); SAFE_DELETE(director); SAFE_DELETE(ceo); getchar(); return 0; } 输出如下: Manager 批准了 1 天假 Director 批准了 2 天假 CEO 批准了 5 天假 给你放长假,以后不用来上班啦!

优秀的个人博客,低调大师

C#接口,类,集成

using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Threading.Tasks; namespace Demo{ public abstract class MyBase { } internal class MyClass : MyBase { } public interface IMyBaseInterface { } internal interface IMyBaseInterface2 { } internal interface IMyInterface : IMyBaseInterface,IMyBaseInterface2 { } internal sealed class MyComplexClass : MyClass,IMyInterface { } class Program { static void Main(string[] args) { MyComplexClass myObj = new MyComplexClass(); Console.WriteLine(myObj.ToString()); Console.ReadKey(); } } }一个namespace可以定义多种类与接口,有意思。本文转自TBHacker博客园博客,原文链接:http://www.cnblogs.com/jiqing9006/p/6758409.html,如需转载请自行联系原作者

优秀的个人博客,低调大师

C#结构函数

using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace Demo { struct CustomerName { public string firstName, lastName; public string Name() { return firstName+" "+lastName; } } class Program { static void Main(string[] args) { CustomerName myCustomer; myCustomer.firstName = "Ji"; myCustomer.lastName = "Qing"; Console.WriteLine("客户的名字:{0}", myCustomer.Name()); Console.ReadKey(); } } } 结构struct函数,有意思。可以尝试利用这个特性。 本文转自TBHacker博客园博客,原文链接:http://www.cnblogs.com/jiqing9006/p/6748212.html,如需转载请自行联系原作者

资源下载

更多资源
Nacos

Nacos

Nacos /nɑ:kəʊs/ 是 Dynamic Naming and Configuration Service 的首字母简称,一个易于构建 AI Agent 应用的动态服务发现、配置管理和AI智能体管理平台。Nacos 致力于帮助您发现、配置和管理微服务及AI智能体应用。Nacos 提供了一组简单易用的特性集,帮助您快速实现动态服务发现、服务配置、服务元数据、流量管理。Nacos 帮助您更敏捷和容易地构建、交付和管理微服务平台。

Spring

Spring

Spring框架(Spring Framework)是由Rod Johnson于2002年提出的开源Java企业级应用框架,旨在通过使用JavaBean替代传统EJB实现方式降低企业级编程开发的复杂性。该框架基于简单性、可测试性和松耦合性设计理念,提供核心容器、应用上下文、数据访问集成等模块,支持整合Hibernate、Struts等第三方框架,其适用范围不仅限于服务器端开发,绝大多数Java应用均可从中受益。

Rocky Linux

Rocky Linux

Rocky Linux(中文名:洛基)是由Gregory Kurtzer于2020年12月发起的企业级Linux发行版,作为CentOS稳定版停止维护后与RHEL(Red Hat Enterprise Linux)完全兼容的开源替代方案,由社区拥有并管理,支持x86_64、aarch64等架构。其通过重新编译RHEL源代码提供长期稳定性,采用模块化包装和SELinux安全架构,默认包含GNOME桌面环境及XFS文件系统,支持十年生命周期更新。

Sublime Text

Sublime Text

Sublime Text具有漂亮的用户界面和强大的功能,例如代码缩略图,Python的插件,代码段等。还可自定义键绑定,菜单和工具栏。Sublime Text 的主要功能包括:拼写检查,书签,完整的 Python API , Goto 功能,即时项目切换,多选择,多窗口等等。Sublime Text 是一个跨平台的编辑器,同时支持Windows、Linux、Mac OS X等操作系统。

用户登录
用户注册