observer_main.cpp 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118
  1. // Copyright (C) 2008-2018 Lorenzo Caminiti
  2. // Distributed under the Boost Software License, Version 1.0 (see accompanying
  3. // file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt).
  4. // See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html
  5. //[mitchell02_observer_main
  6. #include "observer/observer.hpp"
  7. #include "observer/subject.hpp"
  8. #include <boost/contract.hpp>
  9. #include <cassert>
  10. int test_state; // For testing only.
  11. // Implement an actual subject.
  12. class concrete_subject
  13. #define BASES public subject
  14. : BASES
  15. {
  16. friend class boost::contract::access;
  17. typedef BOOST_CONTRACT_BASE_TYPES(BASES) base_types; // Subcontracting.
  18. #undef BASES
  19. public:
  20. typedef int state; // Some state being observed.
  21. concrete_subject() : state_() {
  22. // Could have omitted contracts here (nothing to check).
  23. boost::contract::check c = boost::contract::constructor(this);
  24. }
  25. virtual ~concrete_subject() {
  26. // Could have omitted contracts here (nothing to check).
  27. boost::contract::check c = boost::contract::destructor(this);
  28. }
  29. void set_state(state const& new_state) {
  30. // Could have omitted contracts here (nothing to check).
  31. boost::contract::check c = boost::contract::public_function(this);
  32. state_ = new_state;
  33. assert(state_ == test_state);
  34. notify(); // Notify all observers.
  35. }
  36. state get_state() const {
  37. // Could have omitted contracts here (nothing to check).
  38. boost::contract::check c = boost::contract::public_function(this);
  39. return state_;
  40. }
  41. private:
  42. state state_;
  43. };
  44. // Implement an actual observer.
  45. class concrete_observer
  46. #define BASES public observer
  47. : BASES
  48. {
  49. friend class boost::contract::access;
  50. typedef BOOST_CONTRACT_BASE_TYPES(BASES) base_types; // Subcontracting.
  51. #undef BASES
  52. BOOST_CONTRACT_OVERRIDES(up_to_date_with_subject, update)
  53. public:
  54. // Create concrete observer.
  55. explicit concrete_observer(concrete_subject const& subj) :
  56. subject_(subj), observed_state_() {
  57. // Could have omitted contracts here (nothing to check).
  58. boost::contract::check c = boost::contract::constructor(this);
  59. }
  60. virtual ~concrete_observer() {
  61. // Could have omitted contracts here (nothing to check).
  62. boost::contract::check c = boost::contract::destructor(this);
  63. }
  64. // Implement base virtual functions.
  65. bool up_to_date_with_subject(boost::contract::virtual_* v = 0)
  66. const /* override */ {
  67. bool result;
  68. boost::contract::check c = boost::contract::public_function<
  69. override_up_to_date_with_subject
  70. >(v, result, &concrete_observer::up_to_date_with_subject, this);
  71. return result = true; // For simplicity, assume always up-to-date.
  72. }
  73. void update(boost::contract::virtual_* v = 0) /* override */ {
  74. boost::contract::check c = boost::contract::public_function<
  75. override_update>(v, &concrete_observer::update, this);
  76. observed_state_ = subject_.get_state();
  77. assert(observed_state_ == test_state);
  78. }
  79. private:
  80. concrete_subject const& subject_;
  81. concrete_subject::state observed_state_;
  82. };
  83. int main() {
  84. concrete_subject subj;
  85. concrete_observer ob(subj);
  86. subj.attach(&ob);
  87. subj.set_state(test_state = 123);
  88. subj.set_state(test_state = 456);
  89. return 0;
  90. }
  91. //]