xtd 0.2.0
Loading...
Searching...
No Matches
xtd::iobserver< type_t > Class Template Referenceabstract
Inheritance diagram for xtd::iobserver< type_t >:
xtd::interface

Definition

template<typename type_t>
class xtd::iobserver< type_t >

Provides a mechanism for receiving push-based notifications.

Namespace
xtd
Library
xtd.core
Template Parameters
type_tThe object that provides notification information. This type parameter is contravariant. That is, you can use either the type you specified or any type that is less derived
Examples
The following example illustrates the observer design pattern. It defines a location class that contains latitude and longitude information.
struct location {
public:
location(double latitude, double longitude) : latitutde_(latitude), longitude_(longitude) {}
double latitude() const noexcept {return latitutde_;}
double longitude() const noexcept {return longitude_;}
private:
double latitutde_ = .0;
double longitude_ = .0;
};
The location_tracker class provides the xtd::iobservable implementation. Its track_location method is passed a nullable location object that contains the latitude and longitude data. If the Location value is not nullopt, the track_location method calls the xtd::iobserver::on_next method of each observer.
class location_tracker : public iobservable<location> {
public:
location_tracker() = default;
void subscribe(iobserver<location>& observer) noexcept override {
if (find(observers_.begin(), observers_.end(), &observer) == observers_.end())
observers_.push_back(&observer);
}
void unsubscribe(iobserver<location>& observer) noexcept override {
auto iterator = find(observers_.begin(), observers_.end(), &observer);
if (iterator != observers_.end())
observers_.erase(iterator);
}
void track_location(optional<location> loc) {
for (auto observer : observers_) {
if (!loc.has_value())
observer->on_error(location_unknown_exception());
else
observer->on_next(loc.value());
}
}
void end_transmission() {
for (auto observer : observers_)
observer->on_completed();
observers_.clear();
}
private:
vector<iobserver<location>*> observers_;
};
Provides a mechanism for receiving push-based notifications.
Definition iobservable.h:155
Provides a mechanism for receiving push-based notifications.
Definition iobserver.h:154
If the location value is nullopt, the tack_location method instantiates a location_unknown_exception object, which is shown in the following example. It then calls each observer's on_error method and passes it the location_unknown_exception object. Note that location_unknown_exception derives from xtd::system_exception, but does not add any new members.
class location_unknown_exception : public system_exception {
public:
location_unknown_exception() {}
};
Defines the base class for predefined exceptions in the xtd namespace.
Definition system_exception.h:25
Observers subscribe to receive notifications from an location_tracker object by calling its xtd::iobservable::subscribe method. And unsubscribe by calling its xtd::unobservable <type_t>::unsubscribe method. The location_tracker class also includes an @ end_transmission method. When no further location data is available, this method calls each observer's xtd::iobserver::on_completed method, and then clears the internal list of observers.

In this example, the location_reporter class provides the xtd::iobserver implementation. It displays information about the current location to the console. Its constructor includes a name parameter, which allows the location_reporter instance to identify itself in its string output. It also includes a subscribe method, which wraps a call to the provider's xtd::iobservable::subscribe method. The location_reporter class also includes an unsubscribe method, to remove the subscription. The following code defines the location_reporter class.

class location_reporter : iobserver<location> {
public:
location_reporter(ustring name) : name_(name) {}
virtual ~location_reporter() {unsubscribe();}
ustring name() const noexcept {return name_;}
virtual void subscribe(iobservable<location>& provider) {
provider_ = &provider;
provider_->subscribe(*this);
}
void on_completed() noexcept override {
console::write_line("The location Tracker has completed transmitting data to {}.", name());
unsubscribe();
}
void on_error(const exception& e) noexcept override {
console::write_line("{}: The location cannot be determined.", name());
}
void on_next(const location& value) noexcept override {
console::write_line("{}: The current location is {}, {}", name(), value.latitude(), value.longitude());
}
virtual void unsubscribe() {
if (provider_ != nullptr) provider_->unsubscribe(*this);
provider_ = nullptr;
}
private:
ustring name_;
iobservable<location>* provider_ = nullptr;
};
Represents text as a sequence of UTF-8 code units.
Definition ustring.h:47

The following code then instantiates the provider and the observer.

auto main()->int {
// Define a provider and two observers.
location_tracker provider;
location_reporter reporter1 {"Fixed GPS"};
reporter1.subscribe(provider);
location_reporter reporter2 {"Mobile GPS"};
reporter2.subscribe(provider);
provider.track_location(location {47.6456, -122.1312});
reporter1.unsubscribe();
provider.track_location(location {47.6677, -122.1199});
provider.track_location(nullopt);
provider.end_transmission();
}
// The example displays output similar to the following:
//
// Fixed GPS: The current location is 47.6456, -122.1312
// Mobile GPS: The current location is 47.6456, -122.1312
// Mobile GPS: The current location is 47.6677, -122.1199
// Mobile GPS: The location cannot be determined.
// The location Tracker has completed transmitting data to Mobile GPS.

See You can show this example here

Remarks
The xtd::iobserver and xtd::iobservable <type_t> interfaces provide a generalized mechanism for push-based notification, also known as the observer design pattern. The xtd::iobservable interface represents the class that sends notifications (the provider); the xtd::io::bserver <type_t> interface represents the class that receives them (the observer). type_t represents the class that provides the notification information. In some push-based notifications, the xtd::iobserver <type_t> implementation and type_t can represent the same type.
The provider must implement two methods :
* xtd::iobservable::subscribe, that indicates that an observer wants to receive push-based notifications.
* xtd::iobservable::unsubscribe, that indicates that an observer no longer wants receive push-based notifications.
At any given time, a given provider may have zero, one, or multiple observers. The provider is responsible for storing references to observers and ensuring that they are valid before it sends notifications. The xtd::iobservable interface does not make any assumptions about the number of observers or the order in which notifications are sent.
The provider sends the following three kinds of notifications to the observer by calling xtd::iobserver methods:
* The current data. The provider can call the xtd::iobserver::on_next method to pass the observer a type_t object that has current data, changed data, or fresh data.
* An error condition. The provider can call the xtd::iobserver::on_error method to notify the observer that some error condition has occurred.
* No further data. The provider can call the xtd::iobserver::on_completed method to notify the observer that it has finished sending notifications.
Examples
iobservable_iobserver.cpp.

Public Methods

virtual void on_completed () noexcept=0
 Notifies the observer that the provider has finished sending push-based notifications.
 
virtual void on_error (const std::exception &error) noexcept=0
 Notifies the observer that the provider has experienced an error condition.
 
virtual void on_next (const type_t &value) noexcept=0
 Provides the observer with new data.
 

Member Function Documentation

◆ on_completed()

template<typename type_t >
virtual void xtd::iobserver< type_t >::on_completed ( )
pure virtualnoexcept

Notifies the observer that the provider has finished sending push-based notifications.

Examples
The following example provides an implementation of the OnCompleted method in a latitude/longitude tracking application. The method simply reports that no further data is available and calls the provider's IDisposable.Dispose implementation. See the Example section of the IObserver<T> topic for the complete example.
void on_completed() noexcept override {
console::write_line("The location Tracker has completed transmitting data to {}.", name());
unsubscribe();
}
static void write_line()
Writes the current line terminator to the standard output stream using the specified format informati...
virtual void on_completed() noexcept=0
Notifies the observer that the provider has finished sending push-based notifications.

◆ on_error()

template<typename type_t >
virtual void xtd::iobserver< type_t >::on_error ( const std::exception &  error)
pure virtualnoexcept

Notifies the observer that the provider has experienced an error condition.

Parameters
errorn object that provides additional information about the error.
Examples
The following example provides an implementation of the on_error method in a latitude/longitude tracking application. The method simply reports that data is currently unavailable; it does not make use of the std::exception object passed to it as a parameter. See the Example section of the xtd::iobserver<type_t> topic for the complete example.
void on_error(const std::exception& e) noexcept override {
console::write_line("{}: The location cannot be determined.", name());
}
virtual void on_error(const std::exception &error) noexcept=0
Notifies the observer that the provider has experienced an error condition.
@ e
The E key.

◆ on_next()

template<typename type_t >
virtual void xtd::iobserver< type_t >::on_next ( const type_t &  value)
pure virtualnoexcept

Provides the observer with new data.

Parameters
valueThe current notification information.
Examples
The following example provides an implementation of the on_next method in a latitude/longitude tracking application. See the Example section of the iobserver<type_t> topic for the complete example.
void on_next(const location& value) noexcept override {
console::write_line("{}: The current location is {}, {}", name(), value.latitude(), value.longitude());
}
virtual void on_next(const type_t &value) noexcept=0
Provides the observer with new data.

The documentation for this class was generated from the following file: