访问者模式

访问者模式

访问者模式,你可以从表面上理解未访问和采访,就和几个明星的发布会差不多。几个明星或者剧组进行发布会,记者进行采访的时候其顺序一般是一个个明星轮着来,然后记者也是论者了,因为这保证了N*M问题进行时的流畅性,虽然可能比较麻烦,因为有些时候明明一个问题,可以很多明星一起夹杂着回答的。简单来说,访问者模式就是当多个元素共同影响的时候,往往情况时M*N,甚至更多种情况,然后以其中一种元素作为基准,将其他的元素作为客户选择进行分离,这样就可以减少不必要的循环,然后不管里添加那个元素,都不会影响已有的元素结构(比如发布会再加一个明星,其他明星和记者的回答都不会被改变,而只是新增加了一个人的答案而已),而又需要满足开发的拓展性,而诞生的一个模式,专业点就是:作用于同一个对象的不同元素,在使你不改变各元素类的前提下,还可以定义作用域这些元素的新操作。

Visitor:抽象访问者,是其中一个元素的抽象类。比如记者

ConcreteVisitor:具体类,对于某个个体的详细实现。比如各大媒体的记者,属性又什么衣服、工牌、话筒标识等等

Element类:抽象元素类,可以理解为被选为作为基准的那个元素,比如明星。

ConcreteElement:具体类,单个个体的具体属性,

ObjectStrructure:对象结构,用链表或者向量存储基准类的对象,将另外的元素作为参数输入来进行操作。

这里主要使用的双分派思想:接收者的运行时区别和参数区别,简单来说就是M*N的问题,把他分离开来(M*1)*N.

使用场景:

  • 对象对应的类很少改变,但是需要不时定义新的操作
  • 当一个对象需要多元素进行操作,但是又不想他的类里面含有其他元素的时候,又需要较好的拓展性

优点:

  • 单一职责:将结构和作用于结构的逻辑进行分离,降低耦合性
  • 拓展性好:容易增加信息元素

缺点:

  • 但是时增加新的数据结构麻烦了

实操

 

思路:

  1. 将大学录取分数进行分开讨论,进行派生,生成类组
  2. 因为元素需要进行交互,而且不能在自己的类中含有对方类的属性,因此用函数调用的方式
  3. 选定一个基准,并且建立一个数据类(System)进行基准存储,给定接口被外部调用,而其参数就是另外一个元素。双分派:循环的时候分了不同学生、在学校之中也用分数进行讨论
// VisitoModel.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//

#include <iostream>
#include <string>
#include <vector>
using namespace std;
//如果当需要讨论两个甚至多个元素的共同作用,
//你们你就可以使用访问者模式,因为M*N这种情况单独讨论很复杂
//那么你就可以将其分开,以一种未基准进行遍历,另外一种作为参数进行输入,相当于M*1

class CStudents;
class CSchool
{
protected:
    int m_score;
public:
    virtual void isQualified(CStudents* student) {}
};

class CStudents
{
protected:
    string m_name;
    int m_score;
public:
    int getScore() { return m_score; }
    string getName() { return m_name; }
    virtual void isAdmission(CSchool* school) {}
};

class CWuDaSchool:public CSchool
{
public:
    CWuDaSchool() { m_score = 626; }
    void isQualified(CStudents* student)
    {
        if (NULL == student)
            return;
        if (m_score <= student->getScore())
        {
            cout << student->getName();
            cout << "-";
            cout << student->getScore();
            cout << "-WuDa:录取了。" << endl;
        }
        else
        {
            cout << student->getName();
            cout << "-";
            cout << student->getScore();
            cout << "-WuDa:未录取。" << endl;
        }
    }
};
class CHuaKeSchool :public CSchool
{
public:
    CHuaKeSchool() { m_score = 624; }
    void isQualified(CStudents* student)
    {
        if (NULL == student)
            return;
        if (m_score <= student->getScore())
        {
            cout << student->getName();
            cout << "-";
            cout << student->getScore();
            cout << "-HuaKe:录取了。" << endl;
        }
        else
        {
            cout << student->getName();
            cout << "-";
            cout << student->getScore();
            cout << "-HuaKe:未录取。" << endl;
        }
    }
};

class CStudentsA :public CStudents
{
public:
    CStudentsA(string name, int score) { m_score = score; m_name = name; }
    void isAdmission(CSchool* school)
    {
        if (NULL == school)
            return;
        school->isQualified(this);
    }
};
class CStudentsB :public CStudents
{
public:
    CStudentsB(string name, int score) { m_score = score; m_name = name; }
    void isAdmission(CSchool* school)
    {
        if (NULL == school)
            return;
        school->isQualified(this);
    }
};
class CStudentSystem
{
private:
    vector<CStudents*> m_student;
public:
    void addStudent(CStudents* student) { m_student.push_back(student); }
    void toCheck(CSchool* school) 
    {
        if (NULL == school)
            return;
        for (int i = 0; i < m_student.size(); ++i)
        {
            m_student[i]->isAdmission(school);
        }
    }
};
int main()
{
    CStudents *s1 = new CStudentsA("学生1(西藏)", 400);
    CStudents *s2 = new CStudentsB("学生2(武汉)", 625);

    CStudentSystem *allStu = new CStudentSystem();
    allStu->addStudent(s1);
    allStu->addStudent(s2);

    CSchool *school1 = new CWuDaSchool();
    CSchool* school2 = new CHuaKeSchool();

    allStu->toCheck(school1);
    allStu->toCheck(school2);
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值