00001 // -*- C++ -*- 00002 // 00003 // METS lib source file - observer.h 00004 // 00005 /* 00006 * Software License Agreement (BSD License) 00007 * 00008 * Copyright (c) 2006-2012, Mirko Maischberger <mirko.maischberger@gmail.com> 00009 * All rights reserved. 00010 * 00011 * Redistribution and use in source and binary forms, with or without 00012 * modification, are permitted provided that the following conditions 00013 * are met: 00014 * 00015 * * Redistributions of source code must retain the above copyright 00016 * notice, this list of conditions and the following disclaimer. 00017 * * Redistributions in binary form must reproduce the above 00018 * copyright notice, this list of conditions and the following 00019 * disclaimer in the documentation and/or other materials provided 00020 * with the distribution. 00021 * 00022 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 00023 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 00024 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 00025 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 00026 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 00027 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 00028 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 00029 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 00030 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 00031 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 00032 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 00033 * POSSIBILITY OF SUCH DAMAGE. 00034 * 00035 */ 00036 00037 #ifndef METS_OBSERVER_HH_ 00038 #define METS_OBSERVER_HH_ 00039 00040 #include <set> 00041 #include <algorithm> 00042 00043 namespace mets { 00044 00045 template<typename observed_subject> 00046 class observer; // forward declaration 00047 00048 template<typename observed_subject> 00049 class subject; // forward declaration 00050 00055 template<typename observed_subject> 00056 class update_observer 00057 { 00058 public: 00060 update_observer(observed_subject* who) : who_m(who) {} 00062 void 00063 operator()(observer<observed_subject>* o) { o->update(who_m); } 00064 private: 00065 update_observer(); 00066 observed_subject* who_m; 00067 }; 00068 00082 template<typename observed_subject> 00083 class subject 00084 { 00085 public: 00086 virtual 00087 ~subject() {}; 00093 virtual void 00094 attach(observer<observed_subject>& o); 00100 virtual void 00101 detach(observer<observed_subject>& o); 00108 virtual void 00109 notify(); 00110 protected: 00111 subject(); 00112 std::set<observer<observed_subject>*> observers_m; 00113 }; 00114 00125 template<typename observed_subject> 00126 class observer 00127 { 00128 public: 00129 virtual 00130 ~observer() {}; 00136 virtual void 00137 update(observed_subject*) = 0; 00138 protected: 00139 observer() {}; 00140 }; 00141 00142 00143 // Implementation of the template methods in STL 00144 00145 template<typename observed_subject> 00146 subject<observed_subject>::subject() 00147 : observers_m() { } 00148 00149 template<typename observed_subject> 00150 void 00151 subject<observed_subject>::attach(observer<observed_subject>& o) 00152 { observers_m.insert(&o); } 00153 00154 template<typename observed_subject> 00155 void 00156 subject<observed_subject>::detach(observer<observed_subject>& o) 00157 { observers_m.erase(&o); } 00158 00159 template<typename observed_subject> 00160 void 00161 subject<observed_subject>::notify() 00162 { 00163 // upcast the object to the real observer_subject type 00164 observed_subject* real_subject = static_cast<observed_subject*>(this); 00165 std::for_each(observers_m.begin(), observers_m.end(), 00166 update_observer<observed_subject>(real_subject)); 00167 } 00168 00169 } 00170 00171 #endif // METS_OBSERVER_HH_