• 【行为型】Observer模式


        观察者模式意图解决一对多的依赖关系情形中,当被依赖对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新的问题。举个很简单的例子说,假如一个游戏中的角色的某个属性状态发生了变化,此处不妨假设为角色的等级升级了,则相应的在游戏场景中的模型展现([依赖点1])需要跟着调整,并且在UI界面上的角色属性([依赖点2])描述细节中还需要及时更新成新等级值展现给玩家。这边的[依赖点1]与[依赖点2]就依赖于角色的属性,并且对于这两个依赖点来说,属性对它们都是很敏感的,它们需要能够及时感知到这些属性的变动。这种情形下就可考虑使用Observer模式。模式的类关系结构图参考如下:

        模式的编码结构参考如下:

     1 namespace observer
     2 {
     3     // -------- observer --------
     4     class Subject;
     5     class IObserver
     6     {
     7     public:
     8         // some code here........
     9         virtual void update(Subject* pSubject) = 0;
    10 
    11     };//class IObserver
    12 
    13     class ConcreteObserver1 : public IObserver
    14     {
    15     public:
    16         // some code here........
    17         virtual void update(Subject* pSubject) override {
    18             // some code here........
    19             const auto& theState = pSubject->getState();
    20             // some other code here........
    21         }
    22 
    23     };//class ConcreteObserver1
    24 
    25     // -------- subject --------
    26     class Subject
    27     {
    28     public:
    29         // some code here........
    30         virtual void registeObserver(IObserver* pObserver) = 0;
    31         virtual void unregisterObserver(IObserver* pObserver) = 0;
    32         virtual void notify() = 0;
    33 
    34     };//class Subject
    35 
    36     class ConcreteSubject : public Subject
    37     {
    38     public:
    39         // some code here........
    40         virtual void registeObserver(IObserver* pObserver) override {
    41             // some code here........
    42             m_listObservers.push_back(pObserver);
    43         }
    44 
    45         virtual void unregisterObserver(IObserver* pObserver) override {
    46             // some code here........
    47             auto iter = std::find(m_listObservers.begin(), m_listObservers.end(), pObserver);
    48             if (iter != m_listObservers.end()) {
    49                 m_listObservers.erase(iter);
    50             }
    51         }
    52 
    53         virtual void notify() override {
    54             for_each(m_listObservers.begin(), m_listObservers.end(), [](const IObserver* pObj){ pObj->update(this); });
    55         }
    56 
    57     private:
    58         std::list<IObserver*>   m_listObservers;
    59 
    60     };//class ConcreteSubject
    61 
    62 }//namespace observer
    Observer模式编码结构参考

        Observer模式对于面向对象的设计来说,个人认为其意义还是非常重大。试想如果没有该模式的设计,则Observer与Subject间的耦合性将会大大增强。更可怕的是如果一个Observer所依赖的Subject又不止一个的话,那系统 将会是错综复杂的,后期维护将相当可怕。Observer模式使得Observer与Subject的依赖性降到最小,仅仅只是简单地notify出去即可,并且对于Subject根本不知道(也不需要知道)不同的Observer是什么样的对象,它只负责将状态变动及时通知给注册进来的观察者即可。从而Observer与Subject可以很自然地形成层次结构设计,各自的职责分明。

        在某些没有面向对象机制的语言中,是否也有办法实现Observer了?比如c语言。答案是肯定的。实现的技术手段也很简单:function pointer,具体就不详述了。当然该技术在c++中也是适用的,只是既然人家支持面向对象,自然多数人就不会想着函数指针这种费劲的技术手段。但是随着语言的发展、演变,std::function技术的出现,其实会让Observer模式的设计更加便捷,而且其耦合性会更进一步降低,有兴趣的同学可自行思想下。(提示:std::function+auto|std::bind)

  • 相关阅读:
    uniapp IOS使用uni.getLocation获取不到具体城市名字
    uniapp 打开[ios/安卓]GPS定位权限
    for循环中利用计时器使用let和var
    uniapp 调起底部输入框textarea聊天页面被键盘顶起
    父子组件传布尔类型,发现有问题一直传字符串
    Kafka学习-基础知识
    剑指offer-删除链表中重复的节点
    LEACH协议原文详解
    主流机器学习框架
    算法工程师-职位描述
  • 原文地址:https://www.cnblogs.com/tongy0/p/5592539.html
Copyright © 2020-2023  润新知