实现设计模式:访问者模式

访问者模式把数据结构和作用于结构上的操作解耦合,使得操作集合可相对自由地演化。访问者模式适用于数据结构相对稳定算法又易变化的系统。
这里的实现借鉴了loki,并采用C++11,可以作为参考。

namespace dp
{
	struct basic_visiter
	{
		virtual ~basic_visiter() { }
	};

	template<typename R, class... Visitable> struct visiter;
	template<typename R, class First, class... Other>
	struct visiter<R, First, Other...> : public visiter<R, Other...>,
		public visiter<R, First>
	{
	};
	template<typename R, class Visitable>
	struct visiter<R, Visitable>
	{
		typedef R result_type;
		virtual result_type operator()(Visitable&)=0;
	};

	template<class R, class Visiter=basic_visiter>
	struct visitable
	{
		typedef R result_type;
		typedef Visiter visiter_type;
		virtual result_type accept(visiter_type&)=0;
		template<class T>
		result_type accept_impl(T& visited, visiter_type& visiter)
		{
			typedef dp::visiter<result_type, T> visit_type;
			if(visit_type* p=dynamic_cast<visit_type*>(&visiter))
			{
				return (*p)(visited);
			}
			return result_type();
		}
	};
}

#define DEFINE_VISITABLE_EX(result_type, visiter_type) \
    virtual result_type accept(visiter_type& guest) \
    { return visitable<result_type, visiter_type>::accept_impl(*this, guest); }

#define DEFINE_VISITABLE() DEFINE_VISITABLE_EX(result_type, ::dp::basic_visiter)
#define DEFINE_VISITABLE2(result_type) DEFINE_VISITABLE_EX(result_type, ::dp::basic_visiter)

下面是个关于数值运算的例子,有两种数值类型:整数和浮点数;有两种算法:翻倍和求和。

struct MakeDouble;

struct Number : public  dp::visitable<void>, public dp::visitable<double, MakeDouble>
{
	DEFINE_VISITABLE2(void)
	DEFINE_VISITABLE_EX(double, MakeDouble)
};

struct Int : public Number
{
	DEFINE_VISITABLE2(void)
	DEFINE_VISITABLE_EX(double, MakeDouble)
	Int(int i) : v(i) { }
	int v;
};

struct Double : public Number
{
	DEFINE_VISITABLE2(void)
	DEFINE_VISITABLE_EX(double, MakeDouble)
	Double(double d) : v(d) { }
	double v;
};

struct MakeDouble : public dp::basic_visiter,
	public dp::visiter<double, Int, Double>
{
	MakeDouble() { }
	virtual double operator()(Double& v) { return v.v*2; }
	virtual double operator()(Int& v) { return v.v*2; }
};

struct Sum : public dp::basic_visiter, public dp::visiter<void, Int, Double>
{
	Sum() : m_sum(0) {  }
	~Sum() { cout<<"sum: "<<m_sum<<endl; }
	virtual void operator()(Double& v) { m_sum+=v.v; }
	virtual void operator()(Int& v) { m_sum+=v.v; }

private:
	double m_sum;
};

template<typename Visiter>
void visit(std::vector<Number*>& obj, Visiter&& visiter)
{
	std::for_each(obj.begin(), obj.end(), [&](Number* p) { return p->accept(visiter); } );
}

void test()
{
	Int i(2);
	Double d(3.14);

	std::vector<Number*> obj;
	obj.push_back(&i);
	obj.push_back(&d);

	visit(obj, MakeDouble());
	visit(obj, Sum());
}
和标准的访问者模式相比,数据和算法是完全解耦的,既很容易增加新的算法,也很容易增加新的数据类型。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值