著者: Zhai Tianbao Steven
著作権表示: 著作権は著者に帰属します. 商用転載の場合は、著者に連絡して許可を得てください. 非商用転載の場合は、出典を示してください.
1. 訪問者パターンとは?
Visitor パターンは、オブジェクト構造内の要素に対する操作を表す動作ソフトウェア設計パターンです。各要素のクラスを変更せずに、これらの要素に対する操作を定義できます。
このモードは、比較的安定したデータ構造と簡単に変更できるアルゴリズムを持つシステムに適しています。データ構造はビジターであり、アルゴリズム操作はビジターに相当します。
訪問者パターンの利点:
- 優れたスケーラビリティ。要素の操作を拡張するには、訪問者を追加するだけです。
- 単一責任の原則を満たします。関連する操作はビジターとしてカプセル化されるため、ビジターは単一の責任を負います。
- デカップリング。データ構造自体は、それを操作する操作から分離されています。
訪問者パターンの欠点:
- 要素クラスを追加するのは簡単ではありません。追加の要素クラスごとに、ビジターのインターフェースと実装を変更する必要があります。
- 依存性逆転の原則に違反します。訪問者は抽象的な要素よりも具体的な要素に依存しています。
- パッケージを破ります。訪問者は、訪問中の要素の詳細を取得できます。
2.ビジターモード
2.1 構造図
クライアントは主な機能であり、オブジェクト構造には、アクセスする要素のセットと各要素をトラバースする方法が格納されているため、抽象的なビジターは特定の要素に順番に接続してアクセスを完了することができます。
2.2 コード例
シーンの説明: 市長は学校や企業を視察します。
//Visitor.h
/****************************************************/
#pragma once
#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
using namespace std;
class Visitor;
// 抽象元素类-地点(被访问)
class Place
{
public:
// 构造函数
Place(string name) : m_name(name) {}
// 接受访问
virtual void accept(Visitor* visitor) = 0;
// 获取名字
string getName() {
return m_name;
}
private:
string m_name;
};
// 具体元素类-学校
class School : public Place
{
public:
// 构造函数
School(string name) : Place(name) {}
// 接受访问
virtual void accept(Visitor* visitor);
};
// 具体元素类-企业
class Enterprise : public Place
{
public:
// 构造函数
Enterprise(string name) : Place(name) {}
// 接受访问
virtual void accept(Visitor* visitor);
};
// 抽象访问者
class Visitor
{
public:
// 访问学校
virtual void visitSchool(School* school) = 0;
// 访问企业
virtual void visitEnterprise(Enterprise* enterprise) = 0;
};
// 具体访问者-市长
class Mayor : public Visitor
{
public:
// 访问学校
virtual void visitSchool(School* school) {
cout << "市长参观了:" << school->getName() << endl;
cout << "对老师和学生表达了诚挚的慰问。" << endl;
}
// 访问企业
virtual void visitEnterprise(Enterprise* enterprise) {
cout << "市长参观了:" << enterprise->getName() << endl;
cout << "对企业的发展表示肯定。" << endl;
}
};
// 访问行为类
class Visiting
{
public:
// 添加被访问地点
void add(Place* place) {
places.push_back(place);
}
// 删除被访问地点
void remove(Place* place) {
places.erase(std::remove(places.begin(), places.end(), place), places.end());
}
// 进行访问
void accept(Visitor* visitor) {
for (auto place : places) {
place->accept(visitor);
}
}
private:
std::vector<Place*> places;
};
//Visitor.cpp
/****************************************************/
#include "Visitor.h"
// 接受访问
void School::accept(Visitor* visitor) {
visitor->visitSchool(this);
}
// 接受访问
void Enterprise::accept(Visitor* visitor) {
visitor->visitEnterprise(this);
}
//main.cpp
/****************************************************/
#include <iostream>
#include <string>
#include "Visitor.h"
using namespace std;
int main()
{
Visiting *visiting = new Visiting();
Place *school = new School("东华大学");
Place *enterprise = new Enterprise("华为");
Visitor *mayor = new Mayor();
// 添加被访问对象
cout << "首日,";
visiting->add(school);
visiting->add(enterprise);
// 安排市长进行访问
visiting->accept(mayor);
// 次日行程,删除某个被访问对象后再次访问
cout << "次日,";
visiting->remove(school);
visiting->accept(mayor);
// 删除
delete visiting;
delete school;
delete enterprise;
delete mayor;
visiting = nullptr;
school = nullptr;
enterprise = nullptr;
mayor = nullptr;
return 0;
}
プログラム結果は以下の通りです。
訪問者モードは、アクセス操作をアクセスされる要素から分離します. 学校や企業を訪問するとき、訪問者ごとに異なるものや目的があり、この異なるコンテンツは訪問者クラスで実装できます. ただし、このモードは新しい要素を追加するのには適していません。新しい訪問オブジェクトを追加するのと同じように、警察署では、すべての訪問者が警察署を訪問する操作を追加する必要があり、これは開閉の原則に違反しています。
3. まとめ
ビジターモードの理解をより一般的な言葉と直感的なコードルーチンで表現するために最善を尽くします. 思慮に欠ける場所があるかもしれません. 異なる意見がある場合は, コメント欄でお知らせください! 私の例が、訪問者のパターンをよりよく理解するのに役立つことを願っています。
記事がお役に立てば、いいねでお知らせください。とても嬉しいです〜さあ!