C ++ patrones de diseño - patrón de visitante

C ++ patrones de diseño - patrón de visitante

Referencia URL: https: //www.cnblogs.com/suzhou/p/designpattern17visitor.html

intención

Representa una operación de cada elemento de una estructura de papel objeto particular. Se le permite definir el papel no cambie la premisa de la clase de cada elemento en estos elementos de la nueva operación

aplicabilidad

patrón de uso de los visitantes en las siguientes condiciones:
una estructura de clase de objeto contiene muchos objetos
tienen que ser objeto de diversas operaciones no relacionadas y
objetos raramente cambia, a menudo necesita ser modificado o añadido en su funcionamiento
punto a la nota es que los objetos y las interfaces son a menudo el resultado del cambio, que dará lugar a la necesidad de redefinir todas las interfaces de visitantes, puede conducir a un alto precio. Por lo que este caso se define en las operaciones de clase de objeto mejores.

Diagrama de clases

Aquí Insertar imagen Descripción

cooperación

Aquí Insertar imagen Descripción

Ejemplos

Antecedentes: Supongamos que sus problemas informáticos, ir allí para detectar la venta, venta debe decirle detección de desmontar, proceso de detección seguido por dos técnicos responsables de la detección de diferentes funciones.
Análisis: En este ejemplo, dos funciones diferentes arte responsable del visitante se detecta, los respectivos componentes de la computadora es los elementos.
Características: Los componentes del equipo son fijos y no va a cambiar mucho, pero no hay manera de saber si un método para detectar un problema, entonces usted necesita para aumentar las detecciones. En línea con las características del patrón de visitante.

implementaciones C ++ generales

#include <iostream>
#include <string>
#include <functional>
#include <map>
using namespace std;
#include <vector>

class Element;
class CPU;
class VideoCard;
class MainBoard;

class Visitor {
public:
    Visitor(std::string name) {
        visitorName = name;
    }
    virtual void visitCPU( CPU* cpu ) {};
    virtual void visitVideoCard( VideoCard* videoCard ) {};
    virtual void visitMainBoard( MainBoard* mainBoard ) {};

    std::string getName() {
        return this->visitorName;
    };
private:
    std::string visitorName;
};

class Element {
public:
    Element( std::string name ) {
        eleName = name;
    }
    virtual void accept( Visitor* visitor ) {};

    virtual std::string getName() {
        return this->eleName;
    }
private:
    std::string eleName;
};

class CPU : public Element {
public:
    CPU(std::string name) : Element(name) {}

    void accept(Visitor* visitor) {
        visitor->visitCPU(this);
    }
};

class VideoCard : public Element {
public:
    VideoCard(std::string name) : Element(name) {}

    void accept(Visitor* visitor) {
        visitor->visitVideoCard(this);
    }
};

class MainBoard : public Element {
public:
    MainBoard(std::string name) : Element(name) {}

    void accept(Visitor* visitor) {
        visitor->visitMainBoard(this);
    }
};

class CircuitDetector : public Visitor {
public:
    CircuitDetector(std::string name) : Visitor(name) {}

    // checking cpu
    void visitCPU( CPU* cpu ) {
        std::cout << Visitor::getName() << " is checking CPU's circuits.(" << cpu->getName()<<")" << std::endl;
    }

    // checking videoCard
    void visitVideoCard( VideoCard* videoCard ) {
        std::cout << Visitor::getName() << " is checking VideoCard's circuits.(" << videoCard->getName()<<")" << std::endl;
    }

    // checking mainboard
    void visitMainBoard( MainBoard* mainboard ) {
        std::cout << Visitor::getName() << " is checking MainBoard's circuits.(" << mainboard->getName() <<")" << std::endl;
    }

};

class FunctionDetector : public Visitor {
public:
    FunctionDetector(std::string name) : Visitor(name) {}
    virtual void visitCPU( CPU* cpu ) {
        std::cout << Visitor::getName() << " is check CPU's function.(" << cpu->getName() << ")"<< std::endl;
    }

    // checking videoCard
    void visitVideoCard( VideoCard* videoCard ) {
        std::cout << Visitor::getName() << " is checking VideoCard's function.(" << videoCard->getName()<< ")" << std::endl;
    }

    // checking mainboard
    void visitMainBoard( MainBoard* mainboard ) {
        std::cout << Visitor::getName() << " is checking MainBoard's function.(" << mainboard->getName() << ")"<< std::endl;
    }
};


class Computer {
public:
    Computer(CPU* cpu,
             VideoCard* videocard,
             MainBoard* mainboard) {
        elementList.push_back(cpu);
        elementList.push_back(videocard);
        elementList.push_back(mainboard);
    };
    void Accept(Visitor* visitor) {
        for( std::vector<Element*>::iterator i = elementList.begin(); i != elementList.end(); i++ )
        {
            (*i)->accept(visitor);
        }
    };
private:
    std::vector<Element*> elementList;
};

int main(){
    CPU* cpu = new CPU("Intel CPU");
    VideoCard* videocard = new VideoCard("XXX video card");
    MainBoard* mainboard = new MainBoard("HUAWEI mainboard");
    Computer* myComputer = new Computer(cpu, videocard, mainboard);

    CircuitDetector* Dan = new CircuitDetector("CircuitDetector Dan");
    FunctionDetector* Tom = new FunctionDetector("FunctionDetector Tom");

    std::cout << "\nStep 1: Dan is checking computer's circuits." << std::endl;
    myComputer->Accept(Dan);
    std::cout << "\nStep 2: Tom is checking computer's functions." << std::endl;
    myComputer->Accept(Tom);

    return 0;
}

Sobre la base de la plantilla parámetro variable

GOF "Design Patterns" libro también está claro que el problema de la pauta de Visitantes Nota: la estructura del objeto definición de clase raramente cambia, pero a menudo tienen que definir nuevas operaciones en esta estructura. Los cambios en la estructura de las necesidades de clase de objeto de redefinir el interfaz para todos los visitantes, lo que podría tener que pagar un alto precio. Si la estructura de clase de objeto a menudo cambiada, o estas operaciones se define preferiblemente en esas clases.

En otras palabras, el visitante es un modo de visitante debe ser un sistema de sucesión estable, si el sistema de herencia a menudo cambia, que dará lugar a cambios de Visitantes clase base frecuente, así como los tipos de objetos definidos necesitan acceso en la clase base del visitante, cada uno de los tipos de acceso adicionales serán un aumento correspondiente en función virtual pura, en la realización, si la necesidad de añadir un nuevo visitante es ConcreteElement3, es necesario agregar una función virtual pura en el visitante clase base:

virtual void Visit(ConcreteElement3* element) = 0;

De acuerdo con los principios de la programación a las interfaces, debemos confiar en la interfaz y no debe depender de la aplicación, ya que la interfaz es estable y no cambiará. El patrón del visitante no es interfases estables, que pueden conducir a la inestabilidad de todo el sistema, hay un gran riesgo. Para resolver este problema, la forma más fundamental es definir un establo de Visitantes capa de interfaz que no será la adición de nuevos visitantes y modificar la capa de interfaz, la capacidad de definir un establo capa de interfaz de Visitantes ella? La respuesta es sí, puede mejorar mediante C ++ 11, podemos lograr este objetivo.

Por plantilla parámetro variable puede lograr una capa de interfaz estable, utilizando una plantilla parámetro variable puede soportar cualquier número de parámetros característicos, lo que permite cualquier número de visitantes a la capa de interfaz es accesible a los visitantes, eliminando así la necesidad de aumentar se trata de un nuevo visitante de modificar la capa de interfaz, la capa de interfaz de tal manera que el establo.

#include <iostream>
#include <string>
#include <vector>

using namespace std;

/*--------Template--------*/
template <typename... Types>
class Visitor_;
template <typename T, typename... Types>
class Visitor_<T,Types...> : Visitor_<Types...>{
public:
    using Visitor_<Types...>::Visit;//避免覆盖父类的同名方法
    virtual void Visit(T&) = 0;
};
template <typename T>
class Visitor_<T>{
public:
    virtual void Visit(T&) = 0;
};


class Element;
class CPU;
class VideoCard;
class MainBoard;
class Element;

using VisitorBase=Visitor_<CPU,VideoCard,MainBoard> ;

/*------------------*/

class Visitor : public VisitorBase {
public:
    Visitor(std::string&& name) {
        visitorName = std::forward<string>(name);
    }

    std::string getName() {
        return this->visitorName;
    };
private:
    std::string visitorName;
};


class Element {
public:
    Element( std::string&& name ) {
        eleName = std::forward<string>(name);
    }
    virtual void accept( Visitor& visitor ) {};

    virtual std::string getName() {
        return this->eleName;
    }
private:
    std::string eleName;
};

/*----------- Elements -------------*/

class CPU : public Element {
public:
    CPU(std::string name) : Element(std::move(name)) {}

    void accept(Visitor& visitor) override {
        visitor.Visit(*this);
    }
};

class VideoCard : public Element {
public:
    VideoCard(std::string name) : Element(std::move(name)) {}

    void accept(Visitor& visitor) override {
        visitor.Visit(*this);
    }
};

class MainBoard : public Element {
public:
    MainBoard(std::string name) : Element(std::move(name)) {}

    void accept(Visitor& visitor) override {
        visitor.Visit(*this);
    }
};

/*----------- ConcreteVisitor -------------*/

class CircuitDetector : public Visitor{
public:
    CircuitDetector(std::string name) : Visitor(std::move(name)) {}

    // checking cpu
    void Visit(CPU& cpu ) override {
        std::cout << Visitor::getName() << " is checking CPU's circuits.(" << cpu.getName()<<")" << std::endl;
    }

    // checking videoCard
    void Visit( VideoCard& videoCard ) override {
        std::cout << Visitor::getName() << " is checking VideoCard's circuits.(" << videoCard.getName()<<")" << std::endl;
    }

    // checking mainboard
    void Visit( MainBoard& mainboard ) override {
        std::cout << Visitor::getName() << " is checking MainBoard's circuits.(" << mainboard.getName() <<")" << std::endl;
    }

};

class FunctionDetector : public Visitor {
public:
    FunctionDetector(std::string name) : Visitor(std::move(name)) {}
    void Visit( CPU& cpu )  override {
        std::cout << Visitor::getName() << " is check CPU's function.(" << cpu.getName() << ")"<< std::endl;
    }

    // checking videoCard
    void Visit( VideoCard& videoCard ) override  {
        std::cout << Visitor::getName() << " is checking VideoCard's function.(" << videoCard.getName()<< ")" << std::endl;
    }

    // checking mainboard
    void Visit( MainBoard& mainboard ) override {
        std::cout << Visitor::getName() << " is checking MainBoard's function.(" << mainboard.getName() << ")"<< std::endl;
    }
};

/*------------------------*/
class Computer {
public:
    Computer(CPU* cpu,
             VideoCard* videocard,
             MainBoard* mainboard) {
        elementList.push_back(cpu);
        elementList.push_back(videocard);
        elementList.push_back(mainboard);
    };
    void Accept(Visitor& visitor) {
        for( std::vector<Element*>::iterator i = elementList.begin(); i != elementList.end(); i++ )
        {
            (*i)->accept(visitor);
        }
    };
private:
    std::vector<Element*> elementList;
};


int main(){
    CPU* cpu = new CPU("Intel CPU");
    VideoCard* videocard = new VideoCard("XXX video card");
    MainBoard* mainboard = new MainBoard("HUAWEI mainboard");
    Computer* myComputer = new Computer(cpu, videocard, mainboard);

    CircuitDetector* Dan = new CircuitDetector("CircuitDetector Dan");
    FunctionDetector* Tom = new FunctionDetector("FunctionDetector Tom");

    std::cout << "\nStep 1: Dan is checking computer's circuits." << std::endl;
    myComputer->Accept(*Dan);
    std::cout << "\nStep 2: Tom is checking computer's functions." << std::endl;
    myComputer->Accept(*Tom);

    return 0;
}

Publicados 155 artículos originales · ganado elogios 15 · vistas 160 000 +

Supongo que te gusta

Origin blog.csdn.net/wangdamingll/article/details/104676365
Recomendado
Clasificación