c/c++ linux服务器开发相关视频解析:
10个典型面试题分析,你的技术取向如何决定你的职业方向
TCP训练营深入解析TCP/IP协议栈
面试时要求我写一个线程池,花了150行代码才完成。
尽管设计模式已经在面向对象语言中提出,但大多数商业可用的示例似乎都是基于Java 的,而使用C++ 的示例很少。本文使用C++示例来解释设计模式。
设计模式简介
设计模式是主要针对面向对象语言提出的设计哲学,主要提高代码的可重用性、承受变化并最大限度地减少变化的影响。
面向对象特点
封装:隐藏内部实现继承:重用现有代码多态:重写对象的行为
面向对象设计原则
依赖倒置原则:对于接口编程,依赖抽象而不是具体;不应该依赖抽象(稳定)来实现;细节(变化),实现细节应该依赖于抽象。这是因为如果稳定状态依赖于不断变化的状态,那么它们就会变得不稳定。开放和封闭原则:为扩展而开放,为变化而封闭业务需求一直在变化。如果你需要扩展你的程序,保持原有代码不变,灵活使用抽象和继承,让你的程序更具可扩展性。另外,升级、类、模块、功能等可以扩展,但不能修改。单一职责原则:一个类只做一件事,一个类发生改变应该只有一个原因,改变的方向暗示着该类的责任。里氏替换原则:子类必须能够替换其父类。对基类的引用必须对其子类的对象透明可用。这是开闭原则的一种具体实现。接口分离原则:接口尽量少而完整,尽量减少暴露以减少外部交互,只向外界暴露必要的方法。最少为人所知的原则:实体应尽可能少地与其他实体交互。封装变化点,创建适当的边界,允许一个变化,另一个稳定,这样调用者总是稳定的,被调用测试的内部可以改变。更喜欢使用组合而不是继承。另一方面,组合在一定程度上打破了封装性,父类和子类之间的耦合度比较高。接口编程强调接口标准化而不是实现编程。摘要: 不存在一步式设计模式。当你第一次开始编程时,不要过多关注设计模式。总的说来,首先要注重落实。重组后应采取适当的方法来适应设计模式的变化。
模板方法
父类定义算法的骨架,并将一些步骤推迟给子类,以便子类可以重用骨架并添加功能。以开发框架为例,框架开发者决定调用该框架。一些具体的步骤就留给子类作为虚函数来重写。话不多说,让我们继续看代码。
#ifndef __GAME__#define __GAME__#include iostreamclass Game { public: Game() {} void Run() { InitGame() } protected: virtual void StartGame(); '步骤2: 游戏开始' std:endl; } private: void InitGame() { std:cout '步骤1: 开始游戏' std:endl; } void StopGame() { std:cout '停止游戏' std333 60:endl;#endif#include '游戏. h 'class BasketBall : public Game { void StartGame() override { std:cout '开始篮球比赛' std:endl; }};#include 'game.h'class SocketBall : public Game { void StartGame() override { std:cout '插座球开始游戏' std:3336 0endl ; }};#include 'basketball.h'#include 'socketball.h'int main() { game *game=new BasketBall(); game2=new SocketBall() ); (); 删除game2; return 0;}g++ test.cc -std=c++11 ./a.out 输出: 步骤1: 开始游戏篮球比赛步骤3: 停止游戏步骤1: 开始游戏插座球游戏步骤3: 代码是很简单,包含三个步骤:游戏初始化、游戏开始、游戏停止,并且游戏初始化和游戏停止步骤比较统一,由父类定义。游戏。开始游戏是第二步,你可以打篮球或踢足球。以后可以打羽毛球、乒乓球等。每项附加运动都可以重写为从Game 父类继承并开始游戏。实现不同功能并遵守模板方法属性的能力,即如何在确定稳定结构的同时响应子步骤需求的变化。
策略模式
定义一组算法,并一一封装,以便可以相互替换。一般来说,为了解决多个if-else带来的复杂度,如果多个算法类似,策略模式可以是:一般来说,如果您的项目中有多个if-else 分支,并且预感将来会添加更多if-else 分支,则应该使用此策略。图案。
让我们看一个不使用策略模式的示例。以下代码需要额外的计算,例如乘法和除法。添加if-else。这违反了开闭原则。
enum class CalOperation { add, sub};int NoStrategy(CalOperation ope) { if (ope==CalOperation:add) { std:cout '这是一个添加操作' std:endl; } else if (ope==CalOperation:sub) { std:cout 'This是一个sub 是一个运算' std:endl; } //如果以后需要添加乘除之类的运算,还应该加上if-else return 0;} 下面的例子使用策略模式来定义一个包含virtual 的基类Calculation功能。外科手术()。
#ifndef __CALCULATION__#define __CALCULATION__#include iostreamclass Calculation { public: Calculation() {} virtual ~Calculation() {} virtual void action() { std:cout 'base Operations' std:endl }};#endif 继承将添加一个子类。修改基类并重写操作()函数。
#ifndef __ADD__#define __ADD__#include 'calculation.h' class Add : public Calculation { void action() override { std:cout '这是一个加法运算' std:endl }};#endif#ifndef __SUB__#define __SUB__#include '计算。 h'class Sub : public Calculation { void Operation() override { std:cout '这是一个子操作' }} #endifint Strategy() { 计算*cal=new cal-operation();计算*cal2=new Sub() ; //以后可以在工厂模式下改,不违反开闭原则cal2-operation(); 不是很方便吗?如果以后有乘法,只需添加一个继承自基类的子类,用于除法等运算规则即可。
[文章奖励] 我需要C/C++ Linux Server Architect 的学习材料。添加群812855908(教材包括C/C++、Linux、golang技术、Nginx、ZeroMQ、MySQL、Redis、fastdfs、MongoDB、ZK、流媒体、CDN、P2P、K8S、Docker、TCP/IP、协程、DPDK、ffmpeg , ETC。)
观察者模式
定义对象之间的一对多关系,以便当一个对象改变状态时,其他依赖对象接收广播通知并通过面向对象的多态技术执行自定义操作。可以使用技术来减少这种依赖性、减少耦合并改进代码。
#ifndef __observer __ {Define __observer__} {Public3: Observerbase } Virtual Void Update () {{}};#IFndef {{{} {{}} Lath ObserverFirst Child : public ObserverBase { void Update() override { std:cout '第一个子收据notification' std:endl }};#endif#ifndef __OBSERVER_SECOND_CHILD__#define __OBSERVER_SECOND_CHILD__#include 'observer.h'class ObserverSecondChild 33 36 0 public ObserverBase { void Update() override { std:cout '第二个子通知' 60endl }};#endif#include 列表#include 'observer_first_child.h'#include 'observer_next_child.h'class NotifyBase { public: void Add(ObserverBase *ob) {observers.emplace_back(ob ) } ; void Remove(ObserverBase *ob) {observers.remove(ob); } void Notify() { for (autoobserver :observer) { updateobserver() } } private: std:listObserverBase *observer;};int main( ) { ObserverBase *base1=new ObserverFirstChild(); 观察者模式使您可以灵活地控制依赖对象以及动态添加和删除需要通知的对象。
装饰器模式
动态向对象添加附加职责并扩展类的功能。当涉及到添加功能时,使用装饰器模式比简单地从子类继承更加灵活。
例如,我们有一个很大的类别,称为游戏。您可以扩展此类的功能来定义从游戏基类继承的四个子类。当您组合这些函数时,您的对象会打篮球或卡丁车,并且定义多个类来继承自游戏的基类显然不是一个好主意。装饰者模式可以很好地解决这个问题。上面的代码:首先,定义Game基类。
#ifndef __GAME__#define __GAME__#include iostreamclass Game { public: Game() {} virtual ~Game() {} virtual void Skill() { std:cout 'Game Skill' std:endl }}; #endif 定义了kart 和lol 子类Masu。
#ifndef __car_game __定义__car_game __包括'game.h'class cargame :公共游戏{public: void sqkill()覆盖{STD3:3:COUT _游戏__包括'Game h'。 class LolGame : public Game { public: void Skill() override { std:cout 'lol game' std:endl }};#endif 篮球和足球子类也可以继承上面的定义;不能被继承。由于我们需要扩展功能,所以我们首先定义一个装饰类,然后定义继承这个装饰类的篮球和足球子类。
#ifndef __DECORATOR_GAME__#define __DECORATOR_GAME__#include 'game.h'class DecoratorGame { protected: Game *game_; public: DecoratorGame(Game *game) { game_=game; } void Skill() override { game_-Skill() } virtual ~DecoratorGame( ) {}};#endif#ifndef __BASKETBALL__#define __BASKETBALL__#include 'decorator_game.h'class BasketBallGame : public DecoratorGame { public: BasketBallGame(Game *game) : DecoratorGame(game) {} void Skill() override { std:cout '篮球游戏' std:endl; DecoratorGame:Skill();#endif#ifndef __SOCKETBALL__#define __SOCKETBALL__#include 'decorator_game.h'class SocketBallGame { public33 360 Sock etBallGame(game *game) : DecoratorGame(game) {} void Skill() override { std:cout '套接字游戏' std:endl; #endifFinal 使用
#include 'lol_game.h' #include 'decorator_game.h' #include 'basketball.h' #include 'car_game.h' #include 'socketball.h'int main() { 游戏*lol=new LolGame() *; car=new CarGame(); //如果你会打篮球和LOL,你可以这样使用Game: *篮球_lol=new BasketBallGame(lol); std:endl; //会打篮球的人又可以玩卡丁车了。 Game* BasketBallGame=new std:cout std:endl; //会打篮球、卡丁车、足球的人可以使用Game* g.输出=new SocketBallGame(basketball_lol);删除Basketball_car;观察者模式允许你动态地扩展类的角色,动态地组合类的不同特性。如果你看一下代码,你会发现该类继承自其父类,并且还保存一个指向父类的对象指针。装饰器模式。
桥接模式
确定抽象和实现部分并将它们分开,以便可以独立更改。 桥接模式允许更灵活的扩展。如何:使用组合而不是继承。
例如,图形基类可以包括圆形、矩形、多边形等。每个都必须从图形基类继承一个子类,但每个子类还必须绘制图片或颜色:黄色、黑色、白色等。例如,矩形可能需要颜色,例如黄色、黑色、白色或蓝色。如果单纯使用继承的话,就没有太大的灵活性。您可以将图形类型视为抽象部分。绘制颜色作为实现部分并组合使用它们。 以下是如何分离抽象部分和实现部分:
首先提取实现部分(绘图),从这个基类继承多个绘图方法,并重写它们,并将它们作为Shape图形类的成员变量。
#ifndef __SHAPE_DRAW_IMPL__#define __SHAPE_DRAW_IMPL__#include iostreamclass ShapeDrawImpl { public: virtual void Draw()=0; virtual ~ShapeDrawImpl() {}};#endif#ifndef __SHAPE_DRAW_IMPL_RED__#define __SHAPE_DRAW_IMPL_RED__#include 'shape_draw_impl .h' 类ShapeD rawImplRed : 公共ShapeDrawImpl{ public: virtual void Draw() override { std:cout '绘制红色' std:endl; }};#endif#ifndef __SHAPE_DRAW_IMPL_BLACK__#define __SHAPE_DRAW_IMPL_BLACK__#include 'shape_draw_impl.h'class ShapeDrawImplBlack : public ShapeD raw I mpl{ public33 360 virtual void Draw() 重写{ std:cout '绘制黑色' std:endl; }};#endif 上面定义了两种颜色的实现:红色和黑色。下面的示例定义了一个图形类,定义了一个图形基类,保存了绘图实现的句柄,并定义了多个继承的图形。基类的子类、圆形子类和矩形子类。
#ifndef __SHAPE__#define __SHAPE__#include 'shape_draw_impl.h'class Shape { protected: ShapeDrawImpl *impl; public: virtual void Update() {} Shape(ShapeDrawImpl *impl_) : impl(impl_) {}};#endif#ifndef __SHAPE_CIRCLE__# __SHAPE_CIRCLE__#include 'shape.h' 定义类ShapeCircle : p
ublic Shape {public: void Update() override { std::cout << "circle shape update" << std::endl; impl->Draw(); } ShapeCircle(ShapeDrawImpl *imp) : Shape(imp) {}};#endif#ifndef __SHAPE_RECTANGLE__#define __SHAPE_RECTANGLE__#include "shape.h"class ShapeRectangle : public Shape { public: void Update() override { std::cout << "rectangle shape update" << std::endl; impl->Draw(); } ShapeRectangle(ShapeDrawImpl *imp) : Shape(imp) {}};#endif#include "shape_circle.h"#include "shape_rectangle.h"#include "shape_draw_impl_black.h"#include "shape_draw_impl_red.h"int main() { ShapeDrawImpl *impl = new ShapeDrawImplBlack(); Shape* circle = new ShapeCircle(impl); circle->Update(); delete impl; delete circle; return 0;}输出:circle shape updatedraw black通过桥接模式可以更好的应对变化,应对抽象和实现的多种组合变化。
工厂模式
工厂模式属于创建型模式,主要用于创建对象时不向外部暴露创建逻辑,通过一个共同的接口指向新创建的对象,通过面向对象的多态,将创建对象的工作延迟到子类执行,由子类决定实例化哪个对象。用于隔离对象使用者与其具体类型之间的耦合关系,当具体类型经常变化时,可以考虑使用工厂模式。有一个类型的抽象基类,同时又有很多继承该抽象基类的具体类型,我们做的就是使其依赖于抽象而不依赖于具体,实现方式是创建一个工厂基类,在为每个具体类型定义一个可以创建其相应对象的工厂,每一个具体类对应一个具体工厂,工厂类继承自工厂基类,通过工厂基类的多态性就可以决定创建什么类型的对象。上代码:
#ifndef __GAME__#define __GAME__#include <iostream>class Game { public: Game() {} virtual ~Game() {} virtual void Play() { std::cout << "play game" << std::endl; }};#endif#ifndef __BASKETBALL__#define __BASKETBALL__#include "game.h"class BasketBall : public Game { void Play() override { std::cout << "play basketball" << std::endl; }};#endif#ifndef __SOCKETBALL__#define __SOCKETBALL__#include "game.h"class SocketBall : public Game { void Play() override { std::cout << "play socketball" << std::endl; }};#endif可以通过游戏工厂选择创建不同游戏类型的对象
#ifndef __GAME_FACTORY__#define __GAME_FACTORY__#include "game.h"class GameFactory { public: GameFactory() {} virtual ~GameFactory() {} virtual Game* CreateGame() = 0;};#endif#ifndef __BASKETBALL_FACTORY__#define __BASKETBALL_FACTORY__#include "game_factory.h"#include "basketball.h"class BasketBallFactory : public GameFactory { public: Game* CreateGame() override{ return new BasketBall(); };};#endif#ifndef __SOCKETBALL_FACTORY__#define __SOCKETBALL_FACTORY__#include "game_factory.h"#include "socketball.h"class SocketBallFactory : public GameFactory { public: Game* CreateGame() override{ return new SocketBall(); };};#endif#include "basketball_factory.h"#include "socketball_factory.h"int main() { GameFactory* factory = new BasketBallFactory(); Game* game = factory->CreateGame(); game->Play(); delete factory; delete game; factory = new SocketBallFactory(); game = factory->CreateGame(); game->Play(); delete factory; delete game; return 0;}输出:play basketballplay socketball当有新类型增加时,需要添加一个具体类和一个相应的创建工厂,尽管减少了耦合度,但是其实还是比较麻烦的。
抽象工厂方法模式
和工厂方法模式类似,不做过多介绍,说一下定义,抽象工厂方法模式主要提供一个接口,让该接口负责创建多系列“相关或相互的对象”,无需指定具体的类,系列对象指的是某一特定系列下的对象间有相互依赖或相互作用的关系,不同系列的对象之间不能相互依赖,如果没有多系列对象创建的需求变化,没必要使用抽象工厂方法模式,使用简单工厂方法模式就可以,拿上一个举例继续说,游戏类型是一个系列,我们有了一个游戏类型的工厂,以后可能会再加入娱乐圈类型的一个系列,那就在做一个娱乐圈类型的系列工厂,以后可能还有文艺类型的系列,那就再加一个文艺类型的系列工厂,这就有了三个系列的工厂,所以就可以在这三类工厂的基础上再抽象出一个抽象的超级工厂,根据不同需求选择实例化哪一个系列的具体工厂,再创建具体工厂下的具体类型的对象。
原型模式
用于创建重复的对象,定义一个clone接口,通过调用clone接口创建出与原来类型相同的对象,上代码:
#ifndef __GAME__#define __GAME__#include <iostream>class Game { public: virtual Game* clone() = 0; virtual void Play() = 0;};#endif#ifndef __BASKETBALL__#define __BASKETBALL__#include "game.h"class BasketBall : public Game { virtual Game* clone() override { return new BasketBall(); } virtual void Play() override { std::cout << "basketball" << std::endl; }};#endif#include "basketball.h"int main() { Game *game = new BasketBall(); game->Play(); Game* new_game = game->clone(); new_game->Play(); delete game; delete new_game; return 0;}单纯看game不知道它是什么类型,它可能是篮球游戏也可能是足球游戏等,如果想创建一个与它相同类型的对象就可以使用原型模式其实就是实现一个clone接口,如果一个对象的拷贝构造函数比较复杂而自己不想使用拷贝构造的方式创建对象也可以使用原型模式,使用方式见上例。
建造者模式
用于构建一个复杂的大的对象,一个复杂的对象通常需要一步步才可以构建完成,建造者模式强调的是一步步创建对象,并通过相同的构建过程可以获得不同的结果对象,一般来说建造者对象不是直接返回的,与抽象工厂方法区别是抽象工厂方法用于创建多个系列的对象,而建造者模式强调一步步构建对象,并且构建步骤固定,举例:想要构建一个老师类的对象,老师有第一技能和第二技能,第一技能是数学就代表是数学老师,第一技能是英语就代表是语文老师,构造一个老师对象需要先设定老师的第一技能再设定老师的第二技能,强调一步步设定技能,将这一步步的构建过程可以抽象出建造者模式。
首先定义老师类
#ifndef __TEACHER__#define __TEACHER__#include <iostream>#include <string>class Teacher { private: std::string first_skill_; std::string second_skill_; public: void SetFirstSkill(const std::string& skill) { this->first_skill_ = skill; } void SetSecondSkill(const std::string& skill) { this->second_skill_ = skill; }};#endif定义一个老师的抽象构建器,再根据具体老师继承出具体的老师构建器
#ifndef __TEACHER_ABSTRACT_BUILDER__#define __TEACHER_ABSTRACT_BUILDER__#include "teacher.h"class TeacherAbstractBuilder { public: TeacherAbstractBuilder() {} virtual ~TeacherAbstractBuilder() {} virtual void BuildFirstSkill() = 0; virtual void BuildSecondSkill() = 0; virtual Teacher* GetTeacher() = 0;};#endif#ifndef __MATH_TEACHER_BUILDER__#define __MATH_TEACHER_BUILDER__#include "teacher_abstract_builder.h"class MathTeacherBuilder : public TeacherAbstractBuilder { public: MathTeacherBuilder() { this->teacher_ = new Teacher(); } ~MathTeacherBuilder() { delete this->teacher_; } Teacher* GetTeacher() { return this->teacher_; } void BuildFirstSkill() { this->teacher_->SetFirstSkill("math"); } void BuildSecondSkill() { this->teacher_->SetSecondSkill("english"); } private: Teacher* teacher_;};#endif#ifndef __ENGLISH_TEACHER_BUILDER__#define __ENGLISH_TEACHER_BUILDER__#include "teacher_abstract_builder.h"class EnglishTeacherBuilder : public TeacherAbstractBuilder { public: EnglishTeacherBuilder() { this->teacher_ = new Teacher(); } ~EnglishTeacherBuilder() { delete this->teacher_; } Teacher* GetTeacher() { return this->teacher_; } void BuildFirstSkill() { this->teacher_->SetFirstSkill("english"); } void BuildSecondSkill() { this->teacher_->SetSecondSkill("math"); } private: Teacher* teacher_;};#endif定义一个稳定的Director类,由它根据具体的老师构建器决定构建哪一个老师
#ifndef __DIRECTOR__#define __DIRECTOR__#include "teacher_abstract_builder.h"class Director { public: Director(TeacherAbstractBuilder* builder) { this->builder_ = builder; } ~Director() {} void Create() { this->builder_->BuildFirstSkill(); this->builder_->BuildSecondSkill(); } private: TeacherAbstractBuilder* builder_;};#endif使用方法如下:
#include "director.h"#include "english_teacher_builder.h"#include "math_teacher_builder.h"int main() { TeacherAbstractBuilder *builder = new MathTeacherBuilder(); Director *director = new Director(builder); delete builder; delete director; builder = new EnglishTeacherBuilder(); director = new Director(builder); delete builder; delete director; return 0;}通过Director利用不同的具体构建器都采用相同的步骤一步步构建出不同的具体的老师类对象。
单例模式
不多说了,网上太多了,列一段单例的代码:
static SingleTon& GetInstance() { static SingleTon t; return t; }
享元模式
通过共享技术有效支持大量细粒度的对象,主要解决面向对象代价问题,通过共享有效降低创建的对象个数,类似于对象池。
举例:篮球分多种颜色,我想要蓝色的篮球想要红色的篮球这就需要创建两个对象,当我再想要一个蓝色的篮球如果能够继续使用之前的那个对象就更好,通过享元模式可以做到。
#ifndef __BASKETBALL__#define __BASKETBALL__#include <iostream>#include <string>class BasketBall { public: BasketBall(const std::string& color) : color_(color) {} ~BasketBall() {} private: std::string color_;};#endif#ifndef __BASKETBALL_FACTORY__#define __BASKETBALL_FACTORY__#include <unordered_map>#include "basketball.h"class BasketballFactory { private: std::unordered_map<std::string, BasketBall*> map_; public: BasketBall* GetBasketBallWithColor(const std::string& color) { if (map_.find(color) == map_.end()) { BasketBall* p = new BasketBall(color); map_[color] = p; return p; } else { return map_[color]; } }};#endif#include "BasketballFactory.h"int main() { BasketballFactory factory; BasketBall* white_ball1 = factory.GetBasketBallWithColor("white"); BasketBall* black_ball1 = factory.GetBasketBallWithColor("black"); BasketBall* white_ball2 = factory.GetBasketBallWithColor("white"); BasketBall* black_ball2 = factory.GetBasketBallWithColor("black"); std::cout << white_ball1 << std::endl; std::cout << white_ball2 << std::endl; std::cout << black_ball1 << std::endl; std::cout << black_ball2 << std::endl; // remember to delete return 0;}输出:0x7fffe4984e700x7fffe4984e700x7fffe4984f000x7fffe4984f00
外观模式(Facade Pattern)
感觉外观模式没啥特别的,感觉就是做好功能之间边界的划分,做好封装,弄清楚哪部分是稳定的,哪部分是变化的,对外稳定松耦合,对内迭代变化高内聚,子系统的内部外部要做好解耦,为子系统的一组接口提供一个稳定一致的(界面),子系统中的任何变化都不会影响这个(界面)的变化。
代理模式(Proxy Pattern)
为其它对象提供一种代理以控制这个对象的访问,一般对于比较大的对象访问比较困难或者或带来很多麻烦,例如裸指针的使用,所以一般使用智能指针来控制裸指针,使用智能指针也是一种代理模式,举例:A喜欢B想送给B礼物,但是却不认识B,而C却认识B,所以可以把C作为A的代理去送给B礼物,代码:
#ifndef __GIRL__#define __GIRL__#include <iostream>#include <string>class Girl { private: std::string name_; public: Girl(const std::string &name) : name_(name) {} std::string GetName() const noexcept { return name_; }};#endif#ifndef __GIFT__#define __GIFT__#include "girl.h"class Gift { public: virtual void GiveGift() = 0;};#endif#ifndef __GIFT_PROXY__#define __GIFT_PROXY__#include "gift.h"#include "girl.h"class GiftProxy : public Gift { public: GiftProxy(Girl girl) : girl_(girl) {} void GiveGift() override { std::cout << "send " << girl_.GetName() << " gift" << std::endl; } private: Girl girl_;};#endif#include "gift_proxy.h"int main() { Girl lili("lili"); GiftProxy proxy(lili); proxy.GiveGift(); return 0;}如上述代码,通过代理模式就可以给丽丽送礼物。
适配器模式
太常见了,每个人都会用,两个不兼容的接口之间的桥梁,就像耳机转换头,充电器转换头等等都是适配器模式,将一个类的接口转换为客户希望的另一种接口的形式,使得原本由于接口不兼容而不能一起工作的类可以一起工作。
中介模式
使用一个中介对象来封装一系列的对象交互,当多个对象间互相引用且操作比较复杂时可以考虑使用中介模式。如下图所示:左侧五个对象互相依赖,通过中介这个桥梁就可以减少这个依赖。

状态模式
当一个对象的行为依赖于它的状态并且其有很多种状态而且将来还会有更多状态时,如果使用简单的if-else来增加新状态就违反了面向对象的开闭原则,这时可以考虑使用状态模式,将具体的状态做出一个抽象类,也类似于工厂模式,将具体的状态分散于各个子类中,避免了更多的if-else分支,上代码:
#include <iostream>using namespace std;class Context;class State { public: virtual void Handle(Context *context) = 0;};class Context { public: Context(State *state) : state_(state) {} void Request() { if (state_) { state_->Handle(this); } } void ChangeState(State *pState) { state_ = pState; } private: State *state_;};class ConcreteStateA : public State { public: void Handle(Context *context) override { cout << "I am state a" << endl; }};class ConcreteStateB : public State { public: void Handle(Context *context) override { cout << "I am state b" << endl; }};int main() { State *state_a = new ConcreteStateA(); State *state_b = new ConcreteStateB(); Context *context = new Context(state_a); context->Request(); context->ChangeState(state_b); context->Request(); delete context; delete state_b; delete state_a; return 0;}
版权声明:本文转载于今日头条,版权归作者所有,如果侵权,请联系本站编辑删除