访问者模式解决的问题
dynamic_cast
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<iomanip>
#include<algorithm>
#include<map>
#include<vector>
#include<set>
using namespace std;
class A{
public:
virtual ~A(){//只要有虚构函数成了虚函数,那么基类一定是多态的
}
private:
};
class B:public A{
public:
void sayB() {
cout << "this is class B, x = " << x << endl;
}
int x;
};
class C:public A{
public :
void sayC() {
cout << "this is class C, x = " << x << endl;
}
double x;
};
class D:public A{
public :
void sayD() {
cout << "this is class D, x = " << x << endl;
}
string x;
};
int my_dynamic_cast(A *ta) {
char **pa = (char **)(ta);
char **pb = (char **)(new B());
char **pc = (char **)(new C());
char **pd = (char **)(new D());
int ret = -1;
if(pa[0] == pb[0]) ret = 0;
else if(pa[0] == pc[0]) ret = 1;
else if(pa[0] == pd[0]) ret = 2;
return ret;
}
int main() {
srand(time(0));
A *pa;//A是多态
B *pb;
C *pc;
D *pd;
switch(rand() % 3) {
case 0 : pb = new B();pa = pb;pb->x = 123;break;
case 1 : pc = new C();pa = pc;pc->x = 45.6;break;
case 2 : pd = new D();pa = pd;pd->x = "hello haize";break;
}
if((pb = dynamic_cast<B *>(pa))) {//A是不是B对象
cout << "Class B : ";
pb->sayB();
} else if((pc = dynamic_cast<C *>(pa))) {
cout << "Class C : ";
pc->sayC();
} else if((pd = dynamic_cast<D *>(pa))) {
cout << "Class D : ";
pd->sayD();
}
switch(my_dynamic_cast(pa)) {
case 0: ((B *)(pa))->sayB();break;
case 1: ((C *)(pa))->sayC();break;
case 2: ((D *)(pa))->sayD();break;
}
return 0;
}
判断依据: BCD头部存储的虚函数表地址不同的,所有B对象是相同的,通过虚函数地址来判断你当前的对象是不是B对象.
所以原有基类是多态的.
根据父类指针的对象的原始类型,做出不同的响应
访问者模式
#include <iostream>
#include <ctime>
using namespace std;
class B; // +5
class C; // *2
class D; // -4
class E; // +6
class F; // -7
class A {
public :
class IVisitor {//接口类,所有方法都是纯虚函数
public :
virtual void visit(A *) = 0;//ABCDEF需要前置声明
virtual void visit(B *) = 0;
virtual void visit(C *) = 0;
virtual void visit(D *) = 0;
virtual void visit(E *) = 0;
virtual void visit(F *) = 0;
};
virtual void Accept(IVisitor *vis) {//看成来串门的客人,接受访问者对象,代表功能
vis->visit(this);
}
virtual ~A() {}
};
class B : public A {
public :
void Accept(IVisitor *vis) {//派生类访问都相同
vis->visit(this);
}
};
class C : public A {
public :
void Accept(IVisitor *vis) {
vis->visit(this);
}
};
class D : public A {
public :
void Accept(IVisitor *vis) {
vis->visit(this);
}
};
class E : public A {
public :
void Accept(IVisitor *vis) {
vis->visit(this);
}
};
class F : public A {
public :
void Accept(IVisitor *vis) {
vis->visit(this);
}
};
class OutputVisitor : public A::IVisitor {//每一个访问者类都映射这一个功能,此处代表映射功能和输出有关系
public :
virtual void visit(A *obj) {
cout << "this is father class A" << endl;
}
virtual void visit(B *obj) {//接收B类对象时
cout << "this is a class B object" << endl;
}
virtual void visit(C *obj) {//接收C类对象时
cout << "this is a class C object" << endl;
}
virtual void visit(D *obj) {//接收D类对象时
cout << "this is a class D object" << endl;
}
virtual void visit(E *obj) {//接收E类对象时
cout << "this is a class E object" << endl;
}
virtual void visit(F *obj) {//接收F类对象时
cout << "this is a class F object" << endl;
}
};
class CalcVisitor : public A::IVisitor {
public :
CalcVisitor(int val = 1) : val(val) {}
virtual void visit(A *obj) {}
virtual void visit(B *obj) { val += 5; }
virtual void visit(C *obj) { val *= 2; }
virtual void visit(D *obj) { val -= 4; }
virtual void visit(E *obj) { val += 6; }
virtual void visit(F *obj) { val -= 7; }
int val;
};
int main() {
srand(time(0));
A *arr[10];
for (int i = 0; i < 10; i++) {
switch (rand() % 5) {
case 0: arr[i] = new B(); break;
case 1: arr[i] = new C(); break;
case 2: arr[i] = new D(); break;
case 3: arr[i] = new E(); break;
case 4: arr[i] = new F(); break;
}
}
OutputVisitor vis1;//定义一个访问者对象
CalcVisitor vis2;
for (int i = 0; i < 10; i++) {//遍历父亲类指针
arr[i]->Accept(&vis1);
arr[i]->Accept(&vis2);
}
cout << vis2.val << endl;
return 0;
}
A类型地址,执行Accept方法的时候(Accept是一个(纯)虚函数方法),虚函数是跟着对象走的,例如是C类,调用C类中的Accept, 那C勒种的this指针是C*类型,指向传入的指针, 相关访问者方法, this指针不同, 是Output的.直接映射到Output中的方法;
所有功能封装在访问这种, 类型映射通过虚函数完成的.
访问者模式好处:
-
访问者模式增加派生类, 普通模式不会报错, 而此模式会报错未添加的功能.
-
父类指针到功能映射解决很多
if else
问题, 和基类派生类越多, 普通模式效率越低, 此模式直接调用到相关的功能,和派生类数量多少没关系. -
程序设计更清晰, 访问者类的简化清晰.
单例模式
相关类的对象在全局中只有一个
class HttpServer{
public:
static HttpServer *getInstance(){
if(instance == nullptr) {
instance = new HttpServer();
}
return instance;
}
private:
static HttpServer *instance;
HttpServer(){};
HttpServer(const HttpServer &) = delete;
};
HttpServer *HttpServer::instance = nullptr;
int main() {
HttpServer *t1 = HttpServer::getInstance();
//delete t1
HttpServer *t2 = HttpServer::getInstance();
cout << t1 << " " << t2 << endl;
return 0;
}
上面代码有问题:
-
当我们delete t1 时并不报错, 在实际工程中会出现大BUG
修改方法
-
在对线程中有可能出现BUG, 需要加锁
懒汉模式:像一个懒汉一样,需要用到创建实例了程序再去创建实例,不需要创建实例程序就“懒得”去创建实例,这是一种时间换空间的做法,这体现了“懒汉的本性”。
对线程中会影响效率来一个双重验证:
饿汉模式:像一个饿汉一样,不管需不需要用到实例都要去创建实例,即在类产生的时候就创建好实例,这是 一种空 间换时间的做法。作为一个饿汉而言,体现了它的本质——“我全都要”。
完整代码
#include <iostream>
#include <mutex>
using namespace std;
class HttpServer {
public :
static HttpServer *getInstance() {
if (instance == nullptr) {
std::unique_lock<std::mutex> lock(m_mutex);
if (instance == nullptr) {
instance = new HttpServer();
}
}
return instance;
}
private:
static HttpServer *instance;
static std::mutex m_mutex;
HttpServer() {}
HttpServer(const HttpServer &) = delete;
~HttpServer() {}
};
HttpServer *HttpServer::instance = nullptr;
std::mutex HttpServer::m_mutex;
int main() {
HttpServer *t1 = HttpServer::getInstance();
HttpServer *t2 = HttpServer::getInstance();
cout << t1 << " " << t2 << endl;
return 0;
}
抽象工厂模式
抽象类对外描述的对外表现形式
#include <iostream>
#include <ctime>
using namespace std;
class ICar {
public :
class IFactory {
public :
virtual ICar *crearte() = 0;
};
virtual void run() = 0;
protected:
ICar() {}
~ICar() {}
};
class BenzCar : public ICar {
BenzCar() {}
public :
class Facory : public ICar::IFactory {
public :
virtual ICar *crearte() {
return new BenzCar();
}
};
virtual void run() {
cout << "Benz run" << endl;
}
};
class BmwCar : public ICar {
BmwCar() {}
public :
class Facory : public ICar::IFactory {
public :
virtual ICar *crearte() {
return new BmwCar();
}
};
virtual void run() {
cout << "Bmw run" << endl;
}
};
class AudiCar : public ICar {
AudiCar() {}
public :
class Facory : public ICar::IFactory {
public :
virtual ICar *crearte() {
return new AudiCar();
}
};
virtual void run() {
cout << "Audi run" << endl;
}
};
ICar::IFactory *fac[3] = {new BenzCar::Facory(), new AudiCar::Facory, new BmwCar::Facory()};//创建三个工厂
int main() {
srand(time(0));
ICar *cars[10];//10个车
for (int i = 0; i < 10; i++) {
cars[i] = fac[rand() % 3]->crearte();//三个工厂创建各自的车
}
for (int i = 0; i < 10; i++) {
cars[i]->run();//10个车子跑起来
}
return 0;
}
责任链模式
解决了问题:
#include <iostream>
#include <ctime>
using namespace std;
class ICar {
public :
class IFactory {
public :
virtual ICar *crearte() = 0;
};
class IHandler {//责任链
public :
IHandler() : next(nullptr) {}
virtual bool is_valid(int x) = 0;//代表是否能处理
virtual ICar *do_it() = 0;//当可以的时候制作车
IHandler *next//链表结构
};
virtual void run() = 0;
protected:
ICar() {}
~ICar() {}
};
class BenzCar : public ICar {
BenzCar() {}
public :
class Facory : public ICar::IFactory, public ICar::IHandler {//不仅是工厂,还是责任链的问询
public :
virtual ICar *crearte() {
return new BenzCar();
}
virtual bool is_valid(int x) {//Benz处理0需求
return x == 0;
}
virtual ICar *do_it() {
return this->crearte();
}
};
virtual void run() {
cout << "Benz run" << endl;
}
};
class BmwCar : public ICar {
BmwCar() {}
public :
class Facory : public ICar::IFactory, public ICar::IHandler {
public :
virtual ICar *crearte() {
return new BmwCar();
}
virtual bool is_valid(int x) {//Bmw处理1需求
return x == 1;
}
virtual ICar *do_it() {
return this->crearte();
}
};
virtual void run() {
cout << "Bmw run" << endl;
}
};
class AudiCar : public ICar {
AudiCar() {}
public :
class Facory : public ICar::IFactory, public IHandler {
public :
virtual ICar *crearte() {
return new AudiCar();
}
virtual bool is_valid(int x) {//Audi处理2请求
return x == 2;
}
virtual ICar *do_it() {
return this->crearte();
}
};
virtual void run() {
cout << "Audi run" << endl;
}
};
class ChainMaster {//责任链管理者
public :
static ICar::IHandler *getInstance() {//获取责任链的首地址
if (head == nullptr) {
buildChain();//建立责任链
}
return head;
}
private :
static ICar::IHandler *head;//head
static void buildChain() {
head = new BmwCar::Facory();
head->next = new AudiCar::Facory();
head->next->next = new BenzCar::Facory();
return ;
}
};
ICar::IHandler *ChainMaster::head = nullptr;
int main() {
srand(time(0));
ICar *cars[10];
for (int i = 0; i < 10; i++) {
int req = rand() % 3;
for (auto p = ChainMaster::getInstance(); p; p = p->next) {
if (p->is_valid(req)) {
cars[i] = p->do_it();
}
}
}
for (int i = 0; i < 10; i++) {
cars[i]->run();
}
return 0;
}