单例模式
定义:旨在确保类只有一个实例,并提供一个全局访问点来访问该实例。单例模式通常用于需要在整个应用程序中共享相同对象实例的情况,例如全局配置对象、日志对象、数据库连接等。
人话:只在程序程序运行的时候初始化一次,初始化完成之后无论是再执行构造、拷贝构造、移动拷贝构造都不会新创建一个对象。c++最简单的就是使用static修饰类初始化函数和成员变量,因为static在c++中是线程安全的,但是注意在其它语言中不一定。
demo:
public class Singleton {
private static Singleton instance;
private Singleton() {
// 私有化构造函数,防止外部实例化
}
public static Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
}
工厂模式
定义:封装对象的创建过程,使得客户端代码不需要直接实例化对象,而是通过工厂类来创建对象。
demo:
#include <string>
// 实现导出数据的接口, 导出数据的格式包含 xml,json,文本格式txt 后面可能扩展excel格式csv
class IExport {
public:
virtual bool Export(const std::string &data) = 0;
virtual ~IExport(){}
};
class ExportXml : public IExport {
public:
virtual bool Export(const std::string &data) {
return true;
}
};
class ExportJson : public IExport {
public:
virtual bool Export(const std::string &data) {
return true;
}
};
class ExportTxt : public IExport {
public:
virtual bool Export(const std::string &data) {
return true;
}
};
class ExportCSV : public IExport {
public:
virtual bool Export(const std::string &data) {
return true;
}
};
class IExportFactory {
public:
IExportFactory() {
_export = nullptr;
}
virtual ~IExportFactory() {
if (_export) {
delete _export;
_export = nullptr;
}
}
bool Export(const std::string &data) {
if (_export == nullptr) {
_export = NewExport();
}
return _export->Export(data);
}
protected:
virtual IExport * NewExport(/* ... */) = 0;
private:
IExport* _export;
};
class ExportXmlFactory : public IExportFactory {
protected:
virtual IExport * NewExport(/* ... */) {
// 可能有其它操作,或者许多参数
IExport * temp = new ExportXml();
// 可能之后有什么操作
return temp;
}
};
class ExportJsonFactory : public IExportFactory {
protected:
virtual IExport * NewExport(/* ... */) {
// 可能有其它操作,或者许多参数
IExport * temp = new ExportJson;
// 可能之后有什么操作
return temp;
}
};
class ExportTxtFactory : public IExportFactory {
protected:
IExport * NewExport(/* ... */) {
// 可能有其它操作,或者许多参数
IExport * temp = new ExportTxt;
// 可能之后有什么操作
return temp;
}
};
class ExportCSVFactory : public IExportFactory {
protected:
virtual IExport * NewExport(/* ... */) {
// 可能有其它操作,或者许多参数
IExport * temp = new ExportCSV;
// 可能之后有什么操作
return temp;
}
};
int main () {
IExportFactory *factory = new ExportCSVFactory();
factory->Export("hello world");
return 0;
}
抽象工厂
定义:提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。
人话:工厂模式的升级版本,写程序的时候可能有若干个工厂,实现一个工厂创造器/生成器类,获取具体工厂,再通过具体工厂获取实例化的类对象。有条件把所有工厂的结构进行抽象,抽象出一个基类,所有工厂继承自这个基类。
# 抽象产品A
class AbstractProductA:
def operation(self):
pass
# 具体产品A1
class ConcreteProductA1(AbstractProductA):
def operation(self):
return "Product A1 operation"
# 具体产品A2
class ConcreteProductA2(AbstractProductA):
def operation(self):
return "Product A2 operation"
# 抽象产品B
class AbstractProductB:
def operation(self):
pass
# 具体产品B1
class ConcreteProductB1(AbstractProductB):
def operation(self):
return "Product B1 operation"
# 具体产品B2
class ConcreteProductB2(AbstractProductB):
def operation(self):
return "Product B2 operation"
# 抽象工厂
class AbstractFactory:
def create_product_a(self):
pass
def create_product_b(self):
pass
# 具体工厂1
class ConcreteFactory1(AbstractFactory):
def create_product_a(self):
return ConcreteProductA1()
def create_product_b(self):
return ConcreteProductB1()
# 具体工厂2
class ConcreteFactory2(AbstractFactory):
def create_product_a(self):
return ConcreteProductA2()
def create_product_b(self):
return ConcreteProductB2()
# 客户端代码
factory_type = 1
if factory_type == 1:
factory = ConcreteFactory1()
elif factory_type == 2:
factory = ConcreteFactory2()
product_a = factory.create_product_a()
product_b = factory.create_product_b()
print(product_a.operation()) # Output: Product A1 operation
print(product_b.operation()) # Output: Product B1 operation
责任链
定义:许多个对象都有机会处理请求,从而避免请求的发送者与接收者之间的直接耦合。在责任链模式中,请求沿着一个链传递,直到有一个对象处理它为止。
人话:把处理对象封装在一个函数或者类的内部,然后按照执行这些处理对象,每个处理对象可能解决部分问题,直到问题被全部解决。
demo:
#include <memory>
#include <string>
class Context {
public:
std::string name;
int day;
};
// 稳定点 抽象 变化点 扩展 (多态)
// 从单个处理节点出发,我能处理,我处理,我不能处理交给下一个人处理
// 链表关系如何抽象
class HandleByMainProgram;
class HandleByProjMgr;
class HandleByBoss;
class HandleByBeauty;
class IHandler {
public:
IHandler() : next(nullptr) {}
virtual ~IHandler();
void SetNextHandler(IHandler *next) { // 链表关系
next = next;
}
bool Handle(const Context &ctx) {
if (CanHandle(ctx)) {
return HandleRequest(ctx);
} else if (GetNextHandler()) {
return GetNextHandler()->Handle(ctx);
} else {
// err
}
return false;
}
protected:
virtual bool HandleRequest(const Context &ctx) = 0;
virtual bool CanHandle(const Context &ctx) = 0;
IHandler * GetNextHandler() {
return next;
}
private:
IHandler *next; // 组合基类指针
};
class Request {
public:
Request() {
IHandler * h0 = new HandleByBeauty();
IHandler * h1 = new HandleByMainProgram();
IHandler * h2 = new HandleByProjMgr();
IHandler * h3 = new HandleByBoss();
h0->SetNextHandler(h1);
h1->SetNextHandler(h2);
h2->SetNextHandler(h3);
handler = h0;
}
bool Handle(const Context &ctx) {
return handler->Handle(ctx);
}
private:
IHandler *handler;
};
class HandleByMainProgram : public IHandler {
protected:
virtual bool HandleRequest(const Context &ctx){
//
return true;
}
virtual bool CanHandle(const Context &ctx) {
//
if (ctx.day <= 1)
return true;
return false;
}
};
class HandleByProjMgr : public IHandler {
protected:
virtual bool HandleRequest(const Context &ctx){
//
return true;
}
virtual bool CanHandle(const Context &ctx) {
//
if (ctx.day <= 20)
return true;
return false;
}
};
class HandleByBoss : public IHandler {
protected:
virtual bool HandleRequest(const Context &ctx){
//
return true;
}
virtual bool CanHandle(const Context &ctx) {
//
if (ctx.day < 30)
return true;
return false;
}
};
class HandleByBeauty : public IHandler {
protected:
virtual bool HandleRequest(const Context &ctx){
//
return true;
}
virtual bool CanHandle(const Context &ctx) {
//
if (ctx.day <= 3)
return true;
return false;
}
};
int main() {
// 抽象工厂
// nginx http 处理
// 设置下一指针
Context ctx;
auto req = std::make_unique<Request>();
req->Handle(ctx);
return 0;
}
装饰器
定义:过组合和递归组合的方式来动态地增加对象的功能,而不是通过修改现有类的接口来实现功能的扩展。
人话:在不改变原有接口的基础上通过组合、继承等手段重写或扩展原始对象的方法。
demo:
#include <iostream>
// 普通员工有销售奖金,累计奖金,部门经理除此之外还有团队奖金;后面可能会添加环比增长奖金,同时可能产生不同的奖金组合;
// 销售奖金 = 当月销售额 * 4%
// 累计奖金 = 总的回款额 * 0.2%
// 部门奖金 = 团队销售额 * 1%
// 环比奖金 = (当月销售额-上月销售额) * 1%
// 销售后面的参数可能会调整
using namespace std;
class Context {
public:
bool isMgr;
// User user;
// double groupsale;
};
class CalcBonus {
public:
CalcBonus(CalcBonus * c = nullptr) : cc(c) {}
virtual double Calc(Context &ctx) {
return 0.0; // 基本工资
}
virtual ~CalcBonus() {}
protected:
CalcBonus* cc;
};
class CalcMonthBonus : public CalcBonus {
public:
CalcMonthBonus(CalcBonus * c) : CalcBonus(c) {}
virtual double Calc(Context &ctx) {
double mbonus /*= 计算流程忽略*/;
return mbonus + cc->Calc(ctx);
}
};
class CalcSumBonus : public CalcBonus {
public:
CalcSumBonus(CalcBonus * c) : CalcBonus(c) {}
virtual double Calc(Context &ctx) {
double sbonus /*= 计算流程忽略*/;
return sbonus + cc->Calc(ctx);
}
};
class CalcGroupBonus : public CalcBonus {
public:
CalcGroupBonus(CalcBonus * c) : CalcBonus(c) {}
virtual double Calc(Context &ctx) {
double gbnonus /*= 计算流程忽略*/;
return gbnonus + cc->Calc(ctx);
}
};
class CalcCycleBonus : public CalcBonus {
public:
CalcCycleBonus(CalcBonus * c) : CalcBonus(c) {}
virtual double Calc(Context &ctx) {
double gbnonus /*= 计算流程忽略*/;
return gbnonus + cc->Calc(ctx);
}
};
int main() {
// 1. 普通员工
Context ctx1;
CalcBonus *base = new CalcBonus();
CalcBonus *cb1 = new CalcMonthBonus(base);
CalcBonus *cb2 = new CalcSumBonus(cb1);
cb2->Calc(ctx1);
// 2. 部门经理
Context ctx2;
CalcBonus *cb3 = new CalcGroupBonus(cb1);
cb3->Calc(ctx2);
}
组合模式
定义:又叫部分整体模式,是用于把一组相似的对象当作一个单一的对象。组合模式依据树形结构来组合对象,用来表示部分以及整体层次。这种类型的设计模式属于结构型模式,它创建了对象组的树形结构。
人话:类的嵌套,把相似的类存储到一个容器中,一般容器对象和叶子对象通常实现同一个接口或继承同一个抽象类
demo:
class IComponent
{
public:
IComponent(/* args */);
~IComponent();
virtual void Execute() = 0;
virtual void AddChild(IComponent *ele) {}
virtual void RemoveChild(IComponent *ele) {}
};
class Leaf : public IComponent{
public:
virtual void Execute() {
cout << "leaf exxcute" << endl;
}
};
class Composite : public IComponent
{
private:
std::list<IComponent*> _list;
public:
virtual void AddChild(IComponent *ele) {
// ...
}
virtual void RemoveChild(IComponent *ele) {
// ...
}
virtual void Execute() {
for (auto iter = _list.begin(); iter != _list.end(); iter++) {
iter->Execute();
}
}
};
适配器
定义:主要目的是将一个接口转换成客户希望的另一个接口,使得原本由于接口不兼容而不能一起工作的那些类可以协同工作
demo:
#include <iostream>
#include <string>
// MP3播放器接口
class MP3Player {
public:
virtual ~MP3Player() {}
virtual void play(const std::string& audioFilePath) = 0;
};
// WAV播放器类
class WAVPlayer {
public:
void playWAV(const std::string& wavFilePath) {
std::cout << "Playing WAV file: " << wavFilePath << std::endl;
}
};
// WAV转MP3适配器
class WAVtoMP3Adapter : public MP3Player {
private:
WAVPlayer wavPlayer;
public:
void play(const std::string& audioFilePath) override {
// 假设音频文件名后缀转换逻辑,实际上应根据实际情况调整
std::string convertedFilePath = audioFilePath.substr(0, audioFilePath.find_last_of('.')) + ".wav";
wavPlayer.playWAV(convertedFilePath);
}
};
int main() {
// 创建适配器实例,模拟播放MP3文件
WAVtoMP3Adapter adapter;
// 尝试播放一个"MP3"文件,实际上通过适配器播放WAV
adapter.play("favorite_song.mp3");
return 0;
}
这是一条吃饭博客,由挨踢零声赞助。学C/C++就找挨踢零声,加入挨踢零声,面试不挨踢!