New content are available at http://tis-method.org/. All articles from this site will be moved to the new location.

пятница, 5 ноября 2010 г.

Gateway

The basis of this template is a Pimpl and combination (composition, aggregation) technique.
Template add a new layer of indirection to reduce the coupling of interface and implementation and providing a controlled subset of the interface of the aggregated object. In both cases the "external" object - the interface contains the "inner" object - implementation.
So, gateway provide static/dynamic call forwarding from the interface level to the level of implementation.

Structure
The template consists of two parts. The first part - a pointers to class methods list. This types list defines a subset of the available interfaces to the "hidden" object. The second part - a function object, its purpose - return a reference to the object for which we will be directly implemented method calls.

Implementation
Structurally, Gateway is similar to the Chain of responsibility. Most part of interface is designed to routing method calls from 0 to 10 parameters. But if the "chain of responsibility" works with "arbitrary" function object, the Gateway is working with pointers to class methods.

Example
As an example, consider the following task: route method call from interface to the object, which is located on top of the stack.
///
class base
{
public:
 virtual void update( int const i ) = 0;
};
///
class A : public base
{
public:
 virtual void update( int const i )
 { std::cout << "A::update(" << i << ");" << std::endl; }
};
///
class B : public base
{
public:
 virtual void update( int const i )
 { std::cout << "B::update(" << i << ");" << std::endl; }
};
///
typedef void ( base::* base_update_t )( int const );
///
class manager : public z3d::gateway< manager&, LOKI_TYPELIST_1( base_update_t ) >,
 protected std::stack< boost::reference_wrapper< base > >,
 public boost::noncopyable
{
public:
 ///
 manager() : z3d::gateway< manager&, LOKI_TYPELIST_1( base_update_t ) >( boost::ref( *this ), INITLIST_1( &base::update ) )
 {}
 ///
 base& operator()()
 { return stack< boost::reference_wrapper< base > >::top(); }
 ///
 void push( base& p )
 { stack< boost::reference_wrapper< base > >::push( boost::ref( p ) ); }
 ///
 void pop()
 { stack< boost::reference_wrapper< base > >::pop(); }
};

void main()
{
 A a1;
 A a2;
 B b1;
 manager man;
 man.push( b1 );
 man.push( a1 );
 man.call< base_update_t, void >( 0 );
 man.pop();
 man.call< base_update_t, void >( 1 );
 man.push( a2 );
 man.call< base_update_t, void >( 2 );
}

Program output:
A::update(0);
B::update(1);
A::update(2);


Links
File z3d/gateway.hpp from z3d contains template code.


Комментариев нет:

Отправить комментарий