 <p>Whenever I want to decouple the implementation of a piece of logic from where it's needed - in this case the knowledge of "how much data is enough" - I think of a callback function.</p> <p>Presumably the set of all possible data that your class can collect is known (<code>name</code>, <code>age</code>, <code>sex</code> &amp; <code>location</code> in your example). This means all <em>clients</em> of your class (can) know about it also, without increasing the amount of coupling &amp; dependence.</p> <p>My solution is to create an "evaluator" class that encapsulates this logic. An instance of a subclass of this class is created by the client and handed to the data collector at the time of the initial request for data; this object is responsible for deciding (and telling the "collector") when enough data has been collected.</p> <pre><code>#include &lt;string&gt; // The class that decides when enough data has been collected // (Provided to class "collector" by its clients) class evaluator { public: virtual ~evaluator() {}; // Notification callbacks; Returning *this aids in chaining virtual evaluator&amp; name_collected() { return *this; } virtual evaluator&amp; age_collected() { return *this; } virtual evaluator&amp; sex_collected() { return *this; } virtual evaluator&amp; location_collected() { return *this; } // Returns true when sufficient data has been collected virtual bool enough() = 0; }; // The class that collects all the data class collector { public: void collect_data( evaluator&amp; e ) { bool enough = false; while ( !enough ) { // Listen to data source... // When data comes in... if ( /* data is name */ ) { name = /* store data */ enough = e.name_collected().enough(); } else if ( /* data is age */ ) { age = /* store data */ enough = e.age_collected().enough(); } /* etc. */ } } // Data to collect std::string name; int age; char sex; std::string location; }; </code></pre> <p>In your example, you wanted a particular client to be able to specify that the combination of <code>age</code> and <code>sex</code> is sufficient. So you subclass <code>evaluator</code> like so:</p> <pre><code>class age_and_sex_required : public evaluator { public: age_and_sex_required() : got_age( false ) , got_sex( false ) { } virtual age_and_sex_required&amp; age_collected() override { got_age = true; return *this; } virtual age_and_sex_required&amp; sex_collected() override { got_sex = true; return *this; } virtual bool enough() override { return got_age &amp;&amp; got_sex; } private: bool got_age; bool got_sex; }; </code></pre> <p>The client passes an instance of this class when requesting data:</p> <pre><code>collector c; c.collect_data( age_and_sex_required() ); </code></pre> <p>The <code>collect_data</code> method quits and returns when the <code>age_and_sex_required</code> instance reports that the amount of data collected is "enough", and you haven't built any logic, knowledge, enums, whatever, into the <code>collector</code> class. Also, the logic of what constitutes "enough" is <em>infinitely configurable</em> with no further changes to the <code>collector</code> class.</p> <p>----- EDIT -----</p> <p>An alternate version would <em>not</em> use a class with the <code>..._collected()</code> methods but simply a single (typedef'd) function that accepts the <code>collector</code> as a parameter and returns <code>boolean</code>:</p> <pre><code>#include &lt;functional&gt; typedef std::function&lt; bool( collector const&amp; ) &gt; evaluator_t; </code></pre> <p>The code in <code>collector::collect_data(...)</code> would simply call</p> <pre><code>enough = e( *this ); </code></pre> <p>each time a piece of data is collected.</p> <p>This would eliminate the necessity of the separate <code>evaluator</code> abstract interface, but would add dependence on the <code>collector</code> class itself, as the object passed as the <code>evaluator_t</code> function would be responsible for checking the state of the <code>collector</code> object to evaluate whether enough data has been collected (and would require the <code>collector</code> to have sufficient public interface to inquire about its state):</p> <pre><code>bool age_and_sex_required( collector const&amp; c ) { // Assuming "age" and "sex" are initialized to -1 and 'X' to indicate "empty" // (This could be improved by changing the members of "collector" to use // boost::optional&lt;int&gt;, boost::optional&lt;char&gt;, etc.) return (c.age &gt;= 0) &amp;&amp; (c.sex != 'X'); } </code></pre>