C ++の設計パターン - Visitorパターン
参考URL:httpsを://www.cnblogs.com/suzhou/p/designpattern17visitor.html
意図
これは、特定のロールオブジェクト構造の各要素の動作を表します。それはあなたが新しいオペレーティングのこれらの要素の各要素のクラスの前提を変更しない役割を定義することができます
適用性
以下の条件で使用Visitorパターン:
クラスオブジェクトの構造は、多くのオブジェクトが含まれている
多くの異なる無関係な操作のオブジェクトである必要があり、
多くの場合、その動作を変更する必要があるか、追加、変更することはほとんどのオブジェクトいない
ことに注意することオブジェクトとのインタフェースは、多くの場合、変更の結果であること、それは、すべての訪問者インタフェースを再定義する必要になります高い価格につながる可能です。したがって、この場合は、より良いオブジェクトのクラスの操作で定義されています。
クラス図
連携
例
背景:販売はあなたに別の機能を検出するための責任を負う2つの技術に続いて分解したり、検出、検出処理を指示する必要があり、販売を検出するために、そこに乗り越える、あなたのコンピュータの問題を仮定します。
分析:この例では、2つの異なる機能を担う技術ビジターが検出され、コンピュータの各構成要素です。
特徴:コンピュータのコンポーネントが固定されているとあまり変わりませんが、問題を検出する方法は、その後、あなたが検出を増やす必要があるかどうかを調べる方法はありません。Visitorパターンの特性に合わせて。
一般的なC ++の実装
#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;
}
可変パラメータテンプレートに基づいて、
クラス定義のオブジェクト構造はほとんど変化しないが、多くの場合、この構造に新しい操作を定義する必要があります:GOF「デザインパターン」本は、Visitorパターンのノートの問題ことは明らかでもあります。オブジェクトクラスの構造の変化は、高い代償を払う必要があるかもしれない、すべての訪問者のためのインターフェイスを再定義する必要があります。オブジェクトクラス構造は、多くの場合、変更、またはこれらの操作は、好ましくは、それらのクラスに定義されている場合。
言い換えれば、訪問者は、継承システムが頻繁に変更される場合は定義されたオブジェクトタイプは、ビジターベースクラスにアクセスする必要があるとして、それは、頻繁に変更ビジター基底クラスにつながる、安定した連続システムである必要があり、訪問者モードであります各追加のアクセスタイプは、新しい訪問者を追加する必要がConcreteElement3であれば、あなたは、基本クラスの訪問者に、純粋仮想関数を追加する必要があり、本実施形態では、純粋仮想関数の増加に対応、次のようになります。
virtual void Visit(ConcreteElement3* element) = 0;
インターフェイスにプログラミングの原理によると、私たちは、インタフェースに頼る必要があるとのインタフェースが安定しており、変更されませんので、実装に依存すべきではありません。Visitorパターンは、システム全体の不安定化につながることができ安定したインタフェースではない、大きなリスクがあります。この問題を解決するために、最も基本的な方法は、新しい訪問者を追加することはありません安定したビジター界面層を定義するために、界面層、安定したビジター界面層、それを定義する能力を変更するのですか?答えはイエス、私たちはこの目標を達成することができ、C ++ 11で改善されています。
安定した界面層を達成することができ、可変パラメータテンプレート、特性パラメータの任意の数をサポートすることができ、可変パラメータのテンプレートを使用して、インターフェイス層への訪問者の任意の数を可能にすることにより、このような増加への必要性を排除し、来場者にアクセス可能です界面層、安定した、このような界面層を変更するための新しい訪問者です。
#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;
}