c++ 设计模式23讲之访问者模式

访问者模式

定义:

对象结构中对众多的元素进行访问操作,将结构分为访问者对象和元素对象

优点:

(1)增加新的访问很方便

(2)将元素的访问集中到一个访问者对象,而不是在一个个元素类中实现

缺点:

(1)增加新的元素类比较困难,需要需要具体访问者,不满足开闭原则

(2)破坏封装性,访问者对象需要对元素对象进行操作,可能会暴露元素对象内部操作和状态

使用范围:

一个对象结构包含对多个对象的访问,且每个对象有不同的访问操作

如:处方单,药房访问给药,缴费处访问交钱

结构:

visitor_pattern:访问者抽象类

hr_visitor_pattern,pd_visitor_pattern:具体访问者类

element:元素抽象类

a_element,b_element:具体元素类

element_list:元素集合类,负责传入访问者实现元素类的方法回调

 

实现:

namespace behavioral_pattern
{
	class visitor_pattern;
	class element
	{
	public:
		virtual void accept(std::weak_ptr<visitor_pattern> v) {};
		void set(std::string s) { this->str = s; }
		std::string get() { return str; }
	private:
		std::string str;
	};
	class a_element : public element{ void accept(std::weak_ptr<visitor_pattern> v); };
	class b_element : public element{ void accept(std::weak_ptr<visitor_pattern> v); };
	class visitor_pattern
	{
	public:
		virtual void visit(a_element ele) = 0;
		virtual void visit(b_element ele) = 0;
	};
	class hr_visitor_pattern : public visitor_pattern
	{
		virtual void visit(a_element ele);
		virtual void visit(b_element ele);
	};
	class pd_visitor_pattern : public visitor_pattern
	{
		virtual void visit(a_element ele);
		virtual void visit(b_element ele);
	};
	class element_list
	{
	public:
		void insert_element(std::shared_ptr<element> e)
		{
			list_ele.push_back(e);
		}
		void do_visit(std::shared_ptr<visitor_pattern> v)
		{
			for each(auto itr  in list_ele)
			{
				itr.get()->accept(v);
			}
		}
	private:
		std::list<std::shared_ptr<element>> list_ele;
	};
}
void a_element::accept(std::weak_ptr<visitor_pattern> v)
{
	v.lock().get()->visit(*this);
}
void b_element::accept(std::weak_ptr<visitor_pattern> v)
{
	v.lock().get()->visit(*this);
}
void hr_visitor_pattern::visit(a_element ele)
{
	std::cout << "hr_visitor_pattern: a_element: " << ele.get().c_str() << std::endl;
}
void hr_visitor_pattern::visit(b_element ele)
{
	std::cout << "hr_visitor_pattern: b_element: " << ele.get().c_str() << std::endl;
}

void pd_visitor_pattern::visit(a_element ele)
{
	std::cout << "pd_visitor_pattern: a_element: " << ele.get().c_str() << std::endl;
}
void pd_visitor_pattern::visit(b_element ele)
{
	std::cout << "pd_visitor_pattern: b_element: " << ele.get().c_str() << std::endl;
}

测试:

基于GoogleTest 的单元测试框架;框架可参考如下网址:

https://www.cnblogs.com/jycboy/p/gtest_catalog.html

TEST(test_visitor_pattern, success_insert_visit)
{
	std::shared_ptr<element> e1{new a_element()};
	e1.get()->set("aa00");
	std::shared_ptr<element> e2{ new a_element() };
	e2.get()->set("aa11");
	std::shared_ptr<element> e3{ new b_element() };
	e3.get()->set("bb22");

	element_list li;
	li.insert_element(e1);
	li.insert_element(e2);
	li.insert_element(e3);

	std::shared_ptr<visitor_pattern> v{ new pd_visitor_pattern() };
	li.do_visit(v);
}

总结

(1)需在客户端进行元素对象创建,并加到元素集合类中,进行元素遍历访问触发

(2)调用元素集合类的访问方法,传入访问者对象作为参数;遍历元素类实现回调方法

(3)访问者操作元素类不可对源对象进行污染

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值