潘家园做网站公司,wordpress易语言登录,中国建设项目招标网站,海淀网站建设本溪日志#xff1a;程序运行过程中所记录的程序运行状态信息。通过这些信息#xff0c;以便于程序员能够随时根据状态信息#xff0c;对系统的运行状态进行分析。功能#xff1a;能够让用户非常简便的进行日志的输出以及控制。
同步写日志 同步日志是指当输出日志时#xff…日志程序运行过程中所记录的程序运行状态信息。通过这些信息以便于程序员能够随时根据状态信息对系统的运行状态进行分析。功能能够让用户非常简便的进行日志的输出以及控制。
同步写日志 同步日志是指当输出日志时必须等待日志输出语句执行完毕后才能执行后面的业务逻辑语句日志输出语句与程序的业务逻辑语句将在同⼀个线程运行。每次调用⼀次打印日志API就对应⼀次系统调用write写日志文件。 在高并发场景下随着日志数量不断增加同步日志系统容易产生系统瓶颈 一方面大量的日志打印陷入等量的write系统调用有⼀定系统开销。 另一方面使得打印日志的进程附带了大量同步的磁盘IO影响程序性能。 异步写日志 异步日志是指在进行日志输出时日志输出语句与业务逻辑语句并不是在同⼀个线程中运行而是有专门的线程用于进行日志输出操作。业务线程只需要将日志放到⼀个内存缓冲区中不用等待即可继续执行后续业务逻辑作为日志的生产者而日志的落地操作交给单独的日志线程去完成作为日志的消费者, 这是⼀个典型的生产-消费模型。 这样做的好处是即使日志没有真的地完成输出也不会影响程序的主业务可以提高程序的性能 主线程调用日志打印接口成为非阻塞操作同步的磁盘IO从主线程中剥离出来交给单独的线程完成。 不定参宏函数
#include stdio.h
#define LOG(fmt,...) printf([%s:%d] fmt,__FILE__,__LINE__,##__VA_ARGS__);//fmt是格式化字符串包含许多格式化字符要从后面取出各种各样不同的参数来组织字符串 而...标识是不定参而宏__VA_ARGS__是使用不定参。##是告诉我们当不定参是空的时候则取消前面的逗号
int main()
{printf([%s:%d]%s,__FILE__,__LINE__,hello wjj\n);//__FILE__,__LINE__两个宏说明是所在文件和行号。LOG(%s%d\n,wjj,666);LOG(hello wjj\n)//此时不定参是空所以##起了作用。return 0;
} #include iostream
#include cstdarg
void printNum(int n, ...) //打印数字我们首先得确定有多少个数字n代表传入数字的个数而传的数字是不确定的。
{va_list al;va_start(al, n);//获取地址参数的起始地址这里就是获取参数n之后的第一个不定参数的起始地址for (int i 0; i n; i) {int num va_arg(al, int);//从不定参数中获取出⼀个整形参数这也是va_arg函数第二个参数的意思。std::cout num std::endl;}va_end(al);//清空可变参数列表--其实是将al指针置空
}
int main()
{printNum(3,1,2,3);return 0;
}
//printf前面格式化的字符串里面格式化的字符%d、%s告诉我们编译器接下来应该从后面取几个字节的数据当做整型数据还是字符串来进行处理。 //模拟实现一下printf的实现
#include iostream
#include cstdarg
void myprintf(const char *fmt, ...)
{char *res;va_list al;va_start(al, fmt);//fmt有什么格式化的字符决定我们从后面取出什么类型的数据int len vasprintf(res, fmt, al);//int vasprintf(char **strp, const char *fmt, va_list ap);借用res会自己申请空间根据fmt格式化字符从格式化参数列表al里面取出一个一个的参数进行数据组织并放入申请的空间里面去。 va_end(al);std::cout res std::endl;free(res);//要释放
}
int main()
{myprintf(%s-%d, wjj, 25);myprintf(hello wjj);return 0;
}#include iostream
#include cstdarg
#include memory
#include functional
void xprintf() //对函数模板进行特化增加一个无参的形式。
{std::cout std::endl;
}
templatetypename T, typename ...Args//后者定义的是一个不定参参数包类型
void xprintf(const T value, Args ...args)
{std::cout value ;//先打印第一个参数if ((sizeof ...(args)) 0) //获得参数包的个数{xprintf(std::forwardArgs(args)...);//采用一种递归的思想完美转发你传递过来的时候是左值现在就还是左值。 并且还要补充一个无参的形式}else {xprintf();}
}
int main()
{xprintf(wjj);xprintf(wjj, 666);xprintf(hello, wjj, 666);return 0;
} 设计模式
单例模式
⼀个类只能创建⼀个对象即单例模式该设计模式可以保证系统中该类只有⼀个实例并提供⼀个访问它的全局访问点该实例被所有程序模块共享。
//饿汉模式用空间换时间的思想
class Singleton
{
private:static Singleton _eton;//使用static来修饰。这里属于成员声明并非定义类内的静态成员需要在类外进行定义。
private:Singleton():_data(99){std::cout单例对象构造\n;}//构造函数私有化保证类外无法实例化对象只能在类内实例化~Singleton(){}int _data;
public:Singleton(const Singleton) delete;Singleton operator(const Singleton) delete;static Singleton getInstance() //提供一个访问接口{return _eton;}int GetData(){return _data;}
};
Singleton Singleton::_eton;//类内的静态成员需要在类外定义。静态对象的资源是在静态区的它的生命周期随整个程序的它的初始化构造是在我们程序初始化阶段就完成的。不管你用不用这个对象的资源都已经分配了。int main()
{std::coutSingleton::getInstance().GetData()std::endl;//就算没有这行代码这个单例对象也会构造return 0;
} //懒汉模式延迟加载的思想也就是一个对象到用的时候在进行实例化而不是程序一起来不管用与否都进行实例化
//实现方法定义对象的时候是定义一个对象的指针在通过访问接口的时候发现其为空再去new一个对象
class Singleton {
private:Singleton():_data(99){std::cout单例对象构造\n;}//构造函数私有化保证类外无法实例化对象~Singleton(){}int _data;
public: Singleton(const Singleton) delete;Singleton operator(const Singleton) delete;static Singleton getInstance() { static Singleton _eton;//确保C11起静态变量将能够在满⾜thread-sa fe的前提下唯⼀地被构造和析构这里静态局部对象的定义是线程安全的多个线程试图同时初始化同一个静态局部变量时初始化只会发生一次。return _eton; } int GetData(){return _data;}
}; int main()
{std::coutSingleton::getInstance().GetData()std::endl;//没有这行代码这个单例对象不会构造return 0;
} 工厂模式
工厂模式是⼀种创建型设计模式 它提供了⼀种创建对象的最佳⽅式。在工厂模式中我们创建对象 时不会对上层暴露创建逻辑而是通过使用⼀个共同结构来指向新创建的对象以此实现创建-使用的分离。
//简单⼯⼚模式通过参数控制可以⽣产任何产品
// 优点简单粗暴直观易懂。使⽤⼀个⼯⼚⽣产同⼀等级结构下的任意产品
// 缺点
// 1. 所有东西⽣产在⼀起产品太多会导致代码量庞⼤
// 2. 开闭原则遵循(开放拓展关闭修改)的不是太好要新增产品就必须修改⼯⼚⽅法。
class Fruit
{
public:Fruit(){}virtual void show() 0;
};
class Apple : public Fruit
{
public:Apple() {}virtual void show() {std::cout 我是⼀个苹果 std::endl;}
};
class Banana : public Fruit
{
public:Banana() {}virtual void show() {std::cout 我是⼀个⾹蕉 std::endl;}
};class FruitFactory
{
public:static std::shared_ptrFruit create(const std::string name) {if (name 苹果) {return std::make_sharedApple();}else if(name ⾹蕉) {return std::make_sharedBanana();}return std::shared_ptrFruit();}
};
int main()
{std::shared_ptrFruit fruit FruitFactory::create(苹果);fruit-show();fruit FruitFactory::create(⾹蕉);fruit-show();return 0;
} //工厂方法模式:在简单⼯⼚模式下新增多个⼯⼚多个产品每个产品对应⼀个⼯⼚。
#include iostream
#include memory
#includestring
class Fruit
{
public:Fruit() {}virtual void show() 0;
};
class Apple : public Fruit
{
public:Apple() {}virtual void show(){std::cout 我是⼀个苹果 std::endl;}private:std::string _color;
};
class Banana : public Fruit
{
public:Banana() {}virtual void show(){std::cout 我是⼀个⾹蕉 std::endl;}
};
class FruitFactory
{
public:virtual std::shared_ptrFruit create() 0;
};
class AppleFactory : public FruitFactory
{
public:virtual std::shared_ptrFruit create(){return std::make_sharedApple();}
};class BananaFactory : public FruitFactory
{
public:virtual std::shared_ptrFruit create(){return std::make_sharedBanana();}
};int main()
{std::shared_ptrFruitFactory ff(new AppleFactory()); std::shared_ptrFruit fruit_apple ff-create();fruit_apple-show();ff.reset(new BananaFactory());//更改fruit_apple管理的对象std::shared_ptrFruit fruit_banana ff-create();fruit_banana-show();return 0;
}//抽象工厂围绕一个超级工厂创建其他工厂。每个生成的工厂按照工厂模式提供对象。
//思想将工厂抽象成两层抽象工厂 具体简单工厂子类 在工厂子类种生产不同类型的子产品
#includeiostream
#includememory
class Fruit {public:Fruit(){}virtual void show() 0;
};
class Apple : public Fruit {public:Apple() {}virtual void show() {std::cout 我是一个苹果 std::endl;}private:std::string _color;
};
class Banana : public Fruit {public:Banana() {}virtual void show() {std::cout 我是一个香蕉 std::endl;}
};
class Animal {public:virtual void voice() 0;
};
class Lamp: public Animal {public:void voice() { std::cout 咩咩咩\n; }
};
class Dog: public Animal {public:void voice() { std::cout 汪汪汪\n; }
};class Factory //通过这个抽象工厂类派生出水果工厂和动物工厂
{public:virtual std::shared_ptrFruit getFruit(const std::string name) 0;virtual std::shared_ptrAnimal getAnimal(const std::string name) 0;
};class FruitFactory : public Factory {public:virtual std::shared_ptrAnimal getAnimal(const std::string name) {return std::shared_ptrAnimal();//生产水果就采用返回一个空的智能指针就可以了}virtual std::shared_ptrFruit getFruit(const std::string name) {if (name 苹果) {return std::make_sharedApple();}else if(name 香蕉) {return std::make_sharedBanana();}return std::shared_ptrFruit();}
};class AnimalFactory : public Factory {protected:public:virtual std::shared_ptrFruit getFruit(const std::string name) {return std::shared_ptrFruit();}virtual std::shared_ptrAnimal getAnimal(const std::string name) {if (name 小羊) {return std::make_sharedLamp();}else if(name 小狗) {return std::make_sharedDog();}return std::shared_ptrAnimal();}
};class FactoryProducer {public:static std::shared_ptrFactory getFactory(const std::string name) {if (name 动物) {return std::make_sharedAnimalFactory();}else {return std::make_sharedFruitFactory();}}
};int main()
{std::shared_ptrFactory fruit_factory FactoryProducer::getFactory(水果);//先生产水果工厂std::shared_ptrFruit fruit_applefruit_factory-getFruit(苹果);fruit_apple-show();std::shared_ptrFactory animal_factory FactoryProducer::getFactory(动物);//先生动物果工厂std::shared_ptrAnimal animal_doganimal_factory-getAnimal(小狗);animal_dog-voice();return 0;
} 建造者模式
建造者模式是⼀种创建型设计模式 使⽤多个简单的对象⼀步⼀步构建成⼀个复杂的对象能够将⼀ 个复杂的对象的构建与它的表⽰分离提供⼀种创建对象的最佳⽅式。主要⽤于解决对象的构建过于 复杂的问题。
#include iostream
#include memory
#includestring
/*抽象电脑类里面有许多零部件需要安装*/
class Computer {public:using ptr std::shared_ptrComputer;Computer() {}void setBoard(const std::string board) {_board board;}//一个电脑类得由各个下属的子类才能完成构造比如说键盘void setDisplay(const std::string display) {_display display;}//得有显示器virtual void setOs() 0;//得有操作系统这是一个抽象类不同类型电脑得由不同操作系统。std::string toString() {std::string computer Computer:{\n;computer \tboard _board ,\n; computer \tdisplay _display ,\n; computer \tOs _os ,\n; computer }\n;return computer;} protected://方便派生列访问呢std::string _board;//构造电脑需要的三个零部件std::string _display;std::string _os;
};/*派生出具体产品类*/
class MacBook : public Computer {public:using ptr std::shared_ptrMacBook;MacBook() {}virtual void setOs() {_os Max Os X12;}
};/*抽象建造者类将零件建造出来包含创建一个产品对象的各个部件的抽象接口建造者类是先将各个零部件生产出来然后返回具体的对象*/
class Builder {public:using ptr std::shared_ptrBuilder;virtual void buildBoard(const std::string board) 0;virtual void buildDisplay(const std::string display) 0;virtual void buildOs() 0;virtual Computer::ptr build() 0;
};/*具体产品的具体建造者类实现抽象接口构建和组装各个部件*/
class MackBookBuilder : public Builder {public:using ptr std::shared_ptrMackBookBuilder;MackBookBuilder(): _computer(new MacBook()) {}virtual void buildBoard(const std::string board) {_computer-setBoard(board);}virtual void buildDisplay(const std::string display) {_computer-setDisplay(display);}virtual void buildOs() {_computer-setOs();}virtual Computer::ptr build() {return _computer;}private:Computer::ptr _computer;
};/*由于零部件的构造还会有顺序要求所以这里采用指挥者类提供给调用者使用通过指挥者来获取产品*/
class Director {public:Director(Builder* builder):_builder(builder){}//指挥者指挥的是一个Builder对象void construct(const std::string board, const std::string display) //建造对象{_builder-buildBoard(board);_builder-buildDisplay(display);_builder-buildOs();}private:Builder::ptr _builder;
};int main()
{Builder *buidler new MackBookBuilder();//MackBookBuilder建造者建造mac电脑工人建造没有顺序之分std::unique_ptrDirector pd(new Director(buidler));//pd指挥建造者如何建造先做什么后做什么。pd-construct(英特尔主板, LG显示器);Computer::ptr computer buidler-build();std::cout computer-toString();return 0;
} 代理模式
代理模式指代理控制对其他对象的访问 也就是代理对象控制对原对象的引⽤完成原对象基础之上的一些额外功能。
/*房东要把⼀个房⼦通过中介租出而不是从房东手上租房*/
#include iostream
#include string
class RentHouse//租房类
{
public:virtual void rentHouse() 0;
};
/*房东类将房⼦租出去*/
class Landlord : public RentHouse//房东类
{
public:void rentHouse(){std::cout 将房⼦租出去\n;}
};
/*中介代理类代理了房东的类对租房⼦进⾏功能加强实现租房以外的其他功能*/
class Intermediary : public RentHouse
{
public:void rentHouse(){std::cout 发布招租启⽰\n;std::cout 带⼈看房\n;_landlord.rentHouse();std::cout 负责租后维修\n;}
private:Landlord _landlord;
};
int main()
{Intermediary intermediary;intermediary.rentHouse();return 0;
} 项目框架
日志系统: 作用:将一 条消息, 进行格式化称为指定格式的字符串后写入到指定位置 1.日志要写入指定位置(标准输出指定文件滚动文件....)日志系统需要支持将日志消息落地到不同的位置---多落地方向 2.日志写入指定位置支持不同的写入方式(同步,异步) 同步:业务线程自己负责日志的写入(流程简单,但是有可能会因为阻塞导致效率降低) 异步:业务线程将日志放入缓冲区内存,让其他异步线程负责将日志写入指定位置 3.日志输出以日志器为单位支持多日志器(不同的项目组有不同的输出策略)、日志器的管理 模块划分: 日志等级模块枚举出日志分为多少个等级---对不同的日志有不同等级标记- -以便于控制输出 日志消息模块封装-条日志所需的各种要素 (时间,线程ID,文件名,行号日志等级消息主体.....) 消息格式化模块按照指定的格式对于日志消息关键要素进行组织最终得到一个指定格式的字符串