Multiple Object Observer Using std :: unordered_set

I saw implementations of the Observer design pattern in which Observer is responsible for several objects. Most of these implementations are used std::vector<Subject*>to track topics.

Can I do a similar thing using std::unordered_set<weak_ptr<Subject>>instead?

The reason I want to use unordered_setis because I don't need duplicates and I don't need a custom container. As far as I understand, unordered_setthis is a way to go in this situation. Also, is the reason I use weak_ptrit because it should be safer?

If you do not agree, leave a response explaining which container I should use instead. If I used unordered_set, I would have to declare a hash function for weak_ptr, but can this be done simply by using the hash function for the pointer inside, obtained with subjects.lock().get()?

+4
source share
5 answers

First of all, in my answer I will use Subject as the one who sends messages to registered observers, since this is a common use of these two terms.

Can I do a similar thing using instead std::unordered_set<weak_ptr<Observer>>?

. , , weak_ptr, , weak_ptr shared_ptr . , .

, std:: unordered_set > ?

, _ . , . , unique_set , , , .

, , , . , , , Java. , , shared_pointer .

- weak_ptr, , - , observer.lock(). get()?

-, -, /. / .

-, unique_set, , .

, , , , .

+1

Observer Observer . , . . .

Observer : https://sourcemaking.com/design_patterns/observer

:

class Subject;

class Observer
{
public:
    // when notified about a change, the Observer
    // knows which Subject changed, because of the parameter s
    virtual void subjectChanged(Subject* s)=0;

};

class Subject
{
private:
    int m_internalState;
    std::set<Observer*> m_observers;

public:
    void subscribe(Observer* o)
    {
        m_observers.insert(o);
    }

    void unsubscribe(Observer* o);
    {
        m_observers.erase(o);
    }

    void setInternalState(int state)
    {
        auto end=m_observers.end();
        for(auto it=m_observers.begin(); it != end; ++it)
            it->subjectChanged(this);
    }

};

, , . , . vector , Observer , ( - ) .

0

"" ; , . .

. unordered_set , . -, unordered_set.

unordered_set , . , std:: set . , , , , std::vector - (.. std:: set - , ). , std:: set std:: unordered_set.

- std::vector , . std:: lower_bound O (log n). .

std: vector - , , , . weak_ptr, , , shared_ptr.

0

, std::unordered_set .
? , - , .

, . set - ? , weak_ptr - - . Subject.

, , std::vector<std::unique_ptr<Observer>>.

Edit:

++ 11, std::vector<std::function<void(Subject&)>> + .

0
source

The simplest task is to browse with boost::signals2, which has already implemented this for you, for all signatures. The main problem with your approach is that the implementation is tied to a specific signature with a specific subject and observer, which is practically useless compared to the general solution, which applies to all cases.

The Observer sample is not a template, it is a class template.

-2
source

Source: https://habr.com/ru/post/1606051/


All Articles