1. 程式人生 > >設計模式之訪問者模式(visitor)

設計模式之訪問者模式(visitor)

1、定義

在訪問者模式(Visitor Pattern)中,我們使用了一個訪問者類,它改變了元素類的執行演算法。通過這種方式,元素的執行演算法可以隨著訪問者改變而改變。這種型別的設計模式屬於行為型模式。根據模式,元素物件已接受訪問者物件,這樣訪問者物件就可以處理元素物件上的操作。

2、介紹

優點: 1、符合單一職責原則。 2、優秀的擴充套件性。 3、靈活性。

缺點: 1、具體元素對訪問者公佈細節,違反了迪米特原則。 2、具體元素變更比較困難。 3、違反了依賴倒置原則,依賴了具體類,沒有依賴抽象。

使用場景: 1、物件結構中物件對應的類很少改變,但經常需要在此物件結構上定義新的操作。 2、需要對一個物件結構中的物件進行很多不同的並且不相關的操作,而需要避免讓這些操作"汙染"這些物件的類,也不希望在增加新操作時修改這些類。

注意事項:訪問者可以對功能進行統一,可以做報表、UI、攔截器與過濾器。

3、原始碼

類關係圖:

 運用到知識點:將容器中元素型別定義為父類指標,可以在容器中放入子類指標。

3.1、標頭檔案

IVisitor.h

#pragma once
#include<iostream>
using namespace std;
class CCommonEmployee;
class CManager;
class IVisitor
{
public:

	IVisitor(void)
	{
	}

	virtual ~IVisitor(void)
	{
	}
	virtual void Visit(CCommonEmployee commonEmployee) = 0;
	virtual void Visit(CManager manager) = 0;
	virtual int GetTotalSalary() = 0;
};

 BaseVisitor.h

#pragma once
#include "ivisitor.h"
#include "CommonEmployee.h"
#include "Manager.h"
#include<iostream>
using namespace std;
class CBaseVisitor :
	public IVisitor
{
public:
	CBaseVisitor(void);
	~CBaseVisitor(void);
	void Visit(CCommonEmployee commonEmployee);
	void Visit(CManager manager);
	int GetTotalSalary();
private:
	string GetBasicInfo(CEmployee *pemployee);
	string GetManagerInfo(CManager manager);
	string GetCommonEmployee(CCommonEmployee employee);
	static const int MANAGER_COEFFICENT = 5;
	static const int COMMONEMPLOYEE_COEFFICENT = 2;
	int m_commonTotal;
	int m_managerTotal;
	void CalCommonSalary(int salary);
	void CalManagerSalary(int salary);
};

 Employee.h

#pragma once
#include "IVisitor.h"
class CEmployee
{
public:
	static int MALE;
	static int FEMALE;
	CEmployee(void);
	virtual ~CEmployee(void);
	string GetName();
	void SetName(string name);
	int GetSalary();
	void SetSalary(int v);
	int GetSex();
	void SetSex(int v);
	virtual void Accept(IVisitor *pVisitor) = 0;
private:
	string m_name;
	int m_salary;
	int m_sex;
};

 Manager.h

#pragma once
#include "employee.h"
#include "IVisitor.h"
#include <iostream>
using std::string;
class CManager :
	public CEmployee
{
public:
	CManager(void);
	~CManager(void);
	string GetPerformance();
	void SetPerformance(string per);
	void Accept(IVisitor *pVisitor);
protected:
	string GetOtherInfo();
private:
	string m_performance;
};

 CommonEmployee.h

#include "employee.h"
#include "IVisitor.h"
#include <iostream>
using std::string;
class CCommonEmployee :
	public CEmployee
{
public:
	CCommonEmployee(void);
	~CCommonEmployee(void);
	string GetJob();
	void SetJob(string job);
	void Accept(IVisitor *pVisitor);
protected:
	string GetOtherInfo();
private:
	string m_job;
};

3.2、實現

BaseVisitor.cpp

#include "BaseVisitor.h"
CBaseVisitor::CBaseVisitor(void)
{
	m_commonTotal = 0;
	m_managerTotal = 0;
}

CBaseVisitor::~CBaseVisitor(void)
{
}

void CBaseVisitor::Visit(CCommonEmployee commonEmployee)
{
	cout << this->GetCommonEmployee(commonEmployee).c_str() << endl;
	this->CalCommonSalary(commonEmployee.GetSalary());
}

void CBaseVisitor::Visit(CManager manager)
{
	cout << this->GetManagerInfo(manager).c_str() << endl;
	this->CalManagerSalary(manager.GetSalary());
}

string CBaseVisitor::GetBasicInfo(CEmployee *pemployee)
{
	string info = "";
	info.append("姓名:");
	info.append(pemployee->GetName());
	info.append("\t");
	info.append("性別:");
//	info.append(CConvert::ToString(pemployee->GetSex()));
	info.append("\t");
	info.append("薪水:");
//	info.append(CConvert::ToString(pemployee->GetSalary()));
	info.append("\t");
	return info;
}

string CBaseVisitor::GetManagerInfo(CManager manager)
{
	string basicInfo = this->GetBasicInfo(&manager);
	string otherInfo = "";
	otherInfo.append("業績:");
	otherInfo.append(manager.GetPerformance());
	otherInfo.append("\t");
	basicInfo.append(otherInfo);
	return basicInfo;
}

string CBaseVisitor::GetCommonEmployee(CCommonEmployee employee)
{
	string basicInfo = this->GetBasicInfo(&employee);
	string otherInfo = "";
	otherInfo.append("工作:");
	otherInfo.append(employee.GetJob());
	otherInfo.append("\t");
	basicInfo.append(otherInfo);
	return basicInfo;
}

int CBaseVisitor::GetTotalSalary()
{
	return this->m_commonTotal + this->m_managerTotal;
}

void CBaseVisitor::CalCommonSalary(int salary)
{
	this->m_commonTotal += salary;
}

void CBaseVisitor::CalManagerSalary(int salary)
{
	this->m_managerTotal += salary;
}*/
#define _CRT_SECURE_NO_WARNINGS
#include "BaseVisitor.h"
#include <iostream>
using std::string;
using std::cout;
using std::endl;

CBaseVisitor::CBaseVisitor(void)
{
	m_commonTotal = 0;
	m_managerTotal = 0;
}

CBaseVisitor::~CBaseVisitor(void)
{
}

void CBaseVisitor::Visit(CCommonEmployee commonEmployee)
{
	cout << this->GetCommonEmployee(commonEmployee).c_str() << endl;
	this->CalCommonSalary(commonEmployee.GetSalary());
}

void CBaseVisitor::Visit(CManager manager)
{
	cout << this->GetManagerInfo(manager).c_str() << endl;
	this->CalManagerSalary(manager.GetSalary());
}

string CBaseVisitor::GetBasicInfo(CEmployee *pemployee)
{
	string info = "";
	info.append("姓名:");
	info.append(pemployee->GetName());
	info.append("\t");
	info.append("性別:");
	int getsex = pemployee->GetSex();
	char c[32];
	//itoa(getsex, c,10);
	sprintf(c, "%d", getsex);
	info.append(c);
	info.append("\t");
	info.append("薪水:");
	getsex = pemployee->GetSalary();
	//itoa(getsex, c, 10);
	char c1[64]="0";
	sprintf(c1,"%d",getsex);
	info.append(c1);
	info.append("\t");
	return info;
}

string CBaseVisitor::GetManagerInfo(CManager manager)
{
	string basicInfo = this->GetBasicInfo(&manager);
	string otherInfo = "";
	otherInfo.append("業績:");
	otherInfo.append(manager.GetPerformance());
	otherInfo.append("\t");
	basicInfo.append(otherInfo);
	return basicInfo;
}

string CBaseVisitor::GetCommonEmployee(CCommonEmployee employee)
{
	string basicInfo = this->GetBasicInfo(&employee);
	string otherInfo = "";
	otherInfo.append("工作:");
	otherInfo.append(employee.GetJob());
	otherInfo.append("\t");
	basicInfo.append(otherInfo);
	return basicInfo;
}

int CBaseVisitor::GetTotalSalary()
{
	return this->m_commonTotal + this->m_managerTotal;
}

void CBaseVisitor::CalCommonSalary(int salary)
{
	this->m_commonTotal += salary;
}

void CBaseVisitor::CalManagerSalary(int salary)
{
	this->m_managerTotal += salary;
}

 Employee.cpp

#include "Employee.h"
int CEmployee::MALE = 0;
int CEmployee::FEMALE = 1;

CEmployee::CEmployee(void)
{
}

CEmployee::~CEmployee(void)
{
}

string CEmployee::GetName()
{
	return m_name;
}

void CEmployee::SetName(string name)
{
	m_name = name;
}

int CEmployee::GetSalary()
{
	return m_salary;
}

void CEmployee::SetSalary(int v)
{
	m_salary = v;
}

int CEmployee::GetSex()
{
	return m_sex;
}

void CEmployee::SetSex(int v)
{
	m_sex = v;
}

 Manager.cpp

#include "Manager.h"
#include <iostream>
using std::string;

CManager::CManager(void)
{
    this->m_performance = "";
}

CManager::~CManager(void)
{
}

string CManager::GetPerformance()
{
    return m_performance;
}

void CManager::SetPerformance(string per)
{
    this->m_performance = per;
}

string CManager::GetOtherInfo()
{
    string info = "";
    info.append("業績:");
    info.append(this->m_performance);
    info.append("\t");
    return info;
}

void CManager::Accept(IVisitor *pVisitor)
{
    pVisitor->Visit(*this);
}

 CommonEmployee.cpp

#include "CommonEmployee.h"
#include <iostream>
using std::string;


CCommonEmployee::CCommonEmployee(void)
{
    this->m_job = "";
}


CCommonEmployee::~CCommonEmployee(void)
{
}

string CCommonEmployee::GetJob()
{
    return this->m_job;
}

void CCommonEmployee::SetJob(string job)
{
    this->m_job = job;
}

string CCommonEmployee::GetOtherInfo()
{
    string job = "";
    job.append("工作:");
    job.append(this->m_job);
    job.append("\t");
    return job;
}

void CCommonEmployee::Accept(IVisitor *pVisitor)
{
    pVisitor->Visit(*this);
}

 Visitor.cpp

4、結果