【设计模式:command pattern】

#include <functional>
#include <type_traits>
#include <cassert>
#include <exception>
#include <iostream>
#include <typeinfo>
#include <utility>
#include <string_view>
#include <string>
#include <queue>

template < typename _Ty, typename...Args >
constexpr inline
void __print_type( void ){
	if constexpr ( not ::std::is_function_v< ::std::remove_pointer< _Ty> > ){
		auto _Msg = typeid( _Ty ).name();
		::std::clog << _Msg << "\t";
		if constexpr( sizeof...(Args) ) __print_type< Args... >();
		else ::std::endl( ::std::clog );
	}else throw ::std::runtime_error("__print_type: met function object");
}

template < typename _Ty, typename...Args >
inline
void print_type( void ){
	try{ __print_type< _Ty, Args... >(); }
	catch( const ::std::runtime_error& e){
		::std::cerr << e.what();
	}catch(...){
		::std::cerr << "print_type: unknown error";
	}
}

class Command{
protected:
	::std::string_view _Signature;
public:
	Command( void ) = default;
	Command( const ::std::string_view& sign )
		:_Signature( sign ) {}
	virtual ~Command( void ) {}
	virtual void execute( void ) = 0;
	inline
	void SetSignature( const ::std::string_view& sign ){
		_Signature = sign;
	}
	inline
	const char * GetSignature( void ) const{
		return _Signature.data();
	}
	void print_log( ::std::ostream& out ) const{
		char buf[ 64 ] { 0 };
		sprintf( buf,
				 "Command %s is executing...\n",
				 _Signature.data() );
		out << buf << ::std::endl;
	}
};

template < class _Ty >
class Atomic : public Command{
private:
class CallableExcept : public ::std::exception{
private: const char *_Msg { nullptr };
public:
	CallableExcept( const char * str )
		:_Msg( str ) {}
	virtual const char* what( void ) const noexcept{
		return _Msg;
	}
};

protected:
	::std::function< _Ty( void ) > _Action;
	_Ty _Result;
public:
	Atomic( void ) = default;
	template < class _Fn, class...Args >
	Atomic( _Fn&& f, Args&&...args ){
		try {SetAction( f, args... );}
		catch( const CallableExcept& e){
			::std::cerr << e.what();
			::std::endl( ::std::cerr );
			::std::clog.flush();
			print_type<_Ty, decltype( f( args... ) )>();
		}
		catch(...){
			::std::cerr << "print_type: unknown error";
		}
 	}
		
 	virtual ~Atomic( void ) {}
 	
	template < class _Fn, class...Args >
	constexpr
	void SetAction( _Fn&& f, Args&&...args ){
		static_assert( ::std::is_invocable_v< _Fn, Args... > );
		if constexpr( not ::std::is_same< _Ty,
				typename ::std::result_of< _Fn&&(Args&&...) >::type >
				::value )
			throw CallableExcept("_Ty and result type of _Fn mismatch");
		_Action = ::std::bind( ::std::forward< _Fn >( f ),
							   ::std::forward< Args >( args )... );
 	}

	virtual void execute( void ) override{
		Command::print_log( ::std::cout );
		auto _FuncWrapper =
		[this]{
			_Result = _Action();
		};
		::std::invoke( _FuncWrapper );
	}

	inline constexpr
	const _Ty& GetResult( void ) const noexcept{
		return _Result;
	}
};

class Macro : public Command{
private:
class HandleCommandExcept : public ::std::exception{
private: const char *_Msg { nullptr };
public:
	HandleCommandExcept( const char * str )
		:_Msg( str ) {}
	virtual const char* what( void ) noexcept{
		return _Msg;
	}
};
	Command *_Cache { nullptr };
	::std::queue< Command * > _Aggressive;
public:
	Macro( void ) = default;
	Macro( const ::std::string_view& sign )
		: Command( sign ) {}
	virtual void execute( void ) override{
		Command::print_log( ::std::cout );
		while( !_Aggressive.empty() ) single();
	}
	inline
	void single( void ) noexcept{
		( _Aggressive.front() )->execute();
		_Aggressive.pop();
	}
	inline
	void pushCommand( Command *command ) noexcept{
		_Aggressive.push( command );
	}
	inline
	void undoCommand( void ){
		if( _Aggressive.empty() )
			throw HandleCommandExcept( "Aggressive commands empty" );
		_Aggressive.pop();
	}
	inline
	void redoCommand( void ){
		if( !_Cache )
			throw HandleCommandExcept( "No cache command buffered" );
		pushCommand( _Cache );
		_Cache = nullptr;
	}
};

int main( void ){
	Atomic< int > Add( [](const int& a,
						const int& b)->int{
					return a + b;
	}, 2, 3 );
	Add.SetSignature("Calculate 2+3");

	Atomic< double > Div( []( const int& a,
							const int& b)->double{
					return ( double )a/b;
	}, 2, 3);
	Div.SetSignature("Calculate 2/3");

	Atomic< int > Mul( []( const int& a,
						 const int& b)->int{
					return a* b;
	}, 2, 3);
	Mul.SetSignature("Calculate 2*3");

	Macro Complex("Complex");
	Complex.pushCommand( &Add );
	Complex.pushCommand( &Div );
	Complex.SetSignature("Macro : Agressiate Atomic Add & Div");

	Macro Root("Root");
	Root.pushCommand( &Mul );
	Root.pushCommand( &Complex );
	Root.SetSignature("Macro : Agressiate Atomic Mul and Macro Complex");

	Root.execute();
	
	::std::cout << "Atomic Add result:\t"
				<< Add.GetResult();
	::std::endl( ::std::cout );

	::std::cout << "Atomic Div result:\t"
				<< Div.GetResult();
	::std::endl( ::std::cout );

	::std::cout << "Atomic Mul result:\t"
				<< Mul.GetResult();
	::std::endl( ::std::cout );

	return 0;
}

  • 14
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

XNB's Not a Beginner

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值