c++ 第六章 设计模式

访问者模式解决的问题

dynamic_cast

image-20200820112223734

#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;
}

image-20200814154213531

判断依据: 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中的方法;

所有功能封装在访问这种, 类型映射通过虚函数完成的.

访问者模式好处:

  1. 访问者模式增加派生类, 普通模式不会报错, 而此模式会报错未添加的功能.

  2. 父类指针到功能映射解决很多if else问题, 和基类派生类越多, 普通模式效率越低, 此模式直接调用到相关的功能,和派生类数量多少没关系.

  3. 程序设计更清晰, 访问者类的简化清晰.

单例模式

image-20200821105825151

相关类的对象在全局中只有一个

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;
}

上面代码有问题:

  1. 当我们delete t1 时并不报错, 在实际工程中会出现大BUG

    修改方法

image-20200821103651530

  1. 在对线程中有可能出现BUG, 需要加锁

    懒汉模式:像一个懒汉一样,需要用到创建实例了程序再去创建实例,不需要创建实例程序就“懒得”去创建实例,这是一种时间换空间的做法,这体现了“懒汉的本性”。

懒汉模式

​ 对线程中会影响效率来一个双重验证:

image-20200821104622672

​ 饿汉模式:像一个饿汉一样,不管需不需要用到实例都要去创建实例,即在类产生的时候就创建好实例,这是 一种空 间换时间的做法。作为一个饿汉而言,体现了它的本质——“我全都要”。

饿汉模式

完整代码

#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;
}

抽象工厂模式

image-20200821110256635

抽象类对外描述的对外表现形式

image-20200821110936796

image-20200821115018107

#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;
}

责任链模式

image-20200821115558978

image-20200821120033628

解决了问题:image-20200821121002882

#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;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值