• 观察者模式(大话设计模式)C/C++版本


    观察者模式

    在这里插入图片描述

    扩展:观察者模式——委托

    C++

    参考:https://www.cnblogs.com/Galesaur-wcy/p/15905936.html

    #include 
    #include 
    #include 
    #include 
    using namespace std;
    
    // Observer类 抽象观察者,为所有的具体观察者定义一个接口,在得到主题的通知时更新自己。这个接口要做更新接口。
    // 观察者一般用一个抽象类或者接口实现,更新接口通常包含一个Update()方法 这个方法叫做更新方法。
    class Observer
    {
    public:
        virtual void Update(int) = 0;
        virtual ~Observer() = default;
        virtual void SetName(const string &observerName) final
        {
            m_observerName = observerName;
        }
        virtual string GetName() const final
        {
            return m_observerName;
        }
    
    protected:
        string m_observerName;
    };
    
    // Subject类 可翻译为主题或抽象通知者 一般用一个抽象类或者一个接口实现。他把所有对观察者对象的引用保存
    // 在一个聚集里,每个主题都可以又任何数量的观察者。抽象主题提供一个接口,可增加或者删除观察者对象
    class Subject
    {
    public:
        virtual void Attach(shared_ptr<Observer>) = 0;
        virtual void Detach(shared_ptr<Observer>) = 0;
        virtual void Notify() = 0;
    };
    
    // ConcreteObserver 具体观察者 实现抽象观察角色所要求的更新接口,以便使本身的状态与主题的状态相协调.
    // 具体观察者角色可以保存一个指向具体主题对象的引用.具体观察者校色通常用一个具体子类实现
    class ConcreteObserver : public Observer
    {
    public:
        ConcreteObserver(shared_ptr<Subject> pSubject, const string &observerName)
            : m_pSubject(pSubject)
        {
            m_observerName = observerName;
        }
        void Update(int value) override
        {
            cout << "   ConcreteObserver " << m_observerName << " gets the update. New State: " << value << endl;
        }
    
    private:
        shared_ptr<Subject> m_pSubject;
    };
    
    class ConcreteObserver2 : public Observer
    {
    public:
        ConcreteObserver2(shared_ptr<Subject> pSubject, const string &observerName)
            : m_pSubject(pSubject)
        {
            m_observerName = observerName;
        }
        void Update(int value) override
        {
            cout << "   ConcreteObserver2 " << m_observerName << " gets the update. New State: " << value << endl;
        }
    
    private:
        shared_ptr<Subject> m_pSubject;
    };
    
    // ConcreteSubject类,叫做具体主题或者具体通知者..将有关状态存入具体观察者对象;在具体主题内部状态改变时...给所有登记过的观察者发出通知.
    // 具体主题对象通常用一个具体子类实现.
    class ConcreteSubject : public Subject
    {
    public:
        void Attach(shared_ptr<Observer> pObserver)
        {
            m_ObserverList.push_back(pObserver);
        }
        void Detach(shared_ptr<Observer> pObserver)
        {
            m_ObserverList.remove_if([=](const shared_ptr<Observer> &observer)
                                     { return observer == pObserver; });
        }
        void Notify()
        {
            for (const auto &observer : m_ObserverList)
            {
                cout << "   Notifying -> " << observer->GetName() << endl;
                observer->Update(m_iState);
            }
        }
    
        void SetState(int state)
        {
            cout << "State changed to " << state << endl;
            m_iState = state;
        }
    
    private:
        list<shared_ptr<Observer>> m_ObserverList;
        int m_iState;
    };
    
    int main()
    {
        auto pSubject = make_shared<ConcreteSubject>();
    
        auto pObserver = make_shared<ConcreteObserver>(pSubject, "observer1");
        auto pObserver2 = make_shared<ConcreteObserver2>(pSubject, "observer2");
    
        pSubject->Attach(pObserver);
        pSubject->Attach(pObserver2);
    
        pSubject->SetState(2);
        pSubject->Notify();
        cout << endl;
    
        pSubject->Detach(pObserver);
    
        pSubject->SetState(3);
        pSubject->Notify();
        cout << endl;
    
        return 0;
    }
    

    C

    #include 
    #include 
    #include 
    #include 
    
    typedef struct Subject Subject;
    typedef struct Observer
    {
        char *name;
        void (*update)(struct Subject *, int, void *);
    } Observer;
    
    typedef struct Subject
    {
        struct Observer **observers;
        size_t observer_count;
        int state;
    } Subject;
    
    void ConcreteObserverUpdate(struct Subject *subject, int value, void *data)
    {
        printf("   ConcreteObserver get the update. New State: %d\n", value);
    }
    
    void ConcreteObserver2Update(struct Subject *subject, int value, void *data)
    {
        printf("   ConcreteObserver2 get the update. New State: %d\n", value);
    }
    
    void attach(struct Subject *subject, Observer *observer)
    {
        Observer **newObservers = realloc(subject->observers, sizeof(Observer *) * (subject->observer_count + 1));
        if (newObservers == NULL)
        {
            fprintf(stderr, "Memory allocation failed.\n");
            exit(EXIT_FAILURE);
        }
        newObservers[subject->observer_count++] = observer;
        subject->observers = newObservers;
    }
    
    void detach(struct Subject *subject, Observer *observer)
    {
        bool removed = false;
        int i;
        for (i = 0; i < subject->observer_count; ++i)
        {
            if (subject->observers[i] == observer)
            {
                subject->observer_count--;
                removed = true;
                int j;
                for (j = i; j < subject->observer_count; ++j)
                {
                    subject->observers[j] = subject->observers[j + 1];
                }
                break;
            }
        }
        if (!removed)
        {
            fprintf(stderr, "Observer not found.\n");
        }
    }
    
    void notify(struct Subject *subject)
    {
        int i;
        for (i = 0; i < subject->observer_count; ++i)
        {
            printf("   Notifying -> %s\n", subject->observers[i]->name);
            subject->observers[i]->update(subject, subject->state, subject->observers[i]);
        }
    }
    
    void setState(struct Subject *subject, int state)
    {
        printf("state changed......\n");
        subject->state = state;
    }
    
    void safe_free(void *ptr)
    {
        if (ptr)
            free(ptr);
    }
    
    int main()
    {
        Subject *pSubject = (Subject *)malloc(sizeof(Subject));
        pSubject->observers = NULL;
        pSubject->observer_count = 0;
        pSubject->state = 0;
    
        Observer observer1 = {
            .name = strdup("observer1"),
            observer1.update = ConcreteObserverUpdate,
        };
    
        Observer observer2 = {
            .name = strdup("observer2"),
            .update = ConcreteObserver2Update,
        };
    
        attach(pSubject, &observer1);
        attach(pSubject, &observer2);
    
        setState(pSubject, 2);
        notify(pSubject);
        printf("\n");
    
        detach(pSubject, &observer1);
    
        setState(pSubject, 3);
        notify(pSubject);
        printf("\n");
    
        safe_free(observer1.name);
        safe_free(observer2.name);
        safe_free(pSubject->observers);
        safe_free(pSubject);
    
        return 0;
    }
    
  • 相关阅读:
    强烈建议:语文教师能不吃的苦尽量别吃
    MySQL创建数据库、创建表操作和用户权限
    《吐血整理》进阶系列教程-拿捏Fiddler抓包教程(18)-Fiddler如何接口测试,妈妈再也不担心我不会接口测试了
    windows服务器证书算法升级
    facade(门面模式或外观模式)
    Eolink 旗下网关产品各版本功能及性能对比
    scipy在控制理论的应用
    梅斯健康再冲刺上市:研发投入远不及营销费用,启明、腾讯为股东
    代码随想录Day30 贪心05 LeetCode T435无重叠区间 T763划分字母区间 T56 合并区间
    Debian常用命令
  • 原文地址:https://blog.csdn.net/m0_47104421/article/details/139703282