• 设计模式之观察者模式20170714


    行为型设计模式之观察者模式:

    一、含义

    观察者模式也叫做发布订阅模式,定义对象间一种一对多的依赖关系,

    每当一个对象改变状态(被观察者),则所有依赖于它的对象(观察者)都会得到通知并被自动更新

    即被观察者对应状态产生时,会通知所有的观察者,同时观察者被自动更新。

    二、代码说明

    1.主要有两个角色

    1)被观察者

    它必须能够动态地增加、取消观察者,并且状态改变时会通知观察者(这三个个必须有的操作抽象出来),

    同时被观察也有自己的业务逻辑,定义对哪些事件进行通知

    2)观察者

    观察者接收到消息后,即进行update(更新方法)操作(抽象出来),对接收到的信息进行处理。

    每个观察者接收到消息后的处理反应是不同,各个观察这个有自己的处理逻辑

    2.在用C实现过程中也是参考这种思想,不过由于C的局限,使用继承(覆写)代替实现两个接口更好。

    以李斯观察韩非子为例,具体实现如下:

    1)观察者模式使用场景:

     1 /*****************************************************************************
     2 * Copyright (C) 2017-2018 Hanson Yu  All rights reserved.
     3 ------------------------------------------------------------------------------
     4 * File Module        :     ObserverPatternUsage.c
     5 * Description        :     观察者模式的使用
     6 
     7 book@book-desktop:/work/projects/test/DesignPatterns/ObserverPattern$ gcc -o ObserverPatternUsage ObserverLisi.c  ObserverWangsi.c  ObserverPattern.c ObserverPatternUsage.c 
     8 book@book-desktop:/work/projects/test/DesignPatterns/ObserverPattern$ ./ObserverPatternUsage 
     9 韩非子:开始吃饭...
    10 李斯:观察到韩非子活动,开始向秦老板汇报
    11 李斯:报告,秦老板,韩非子有活动了-->韩非子在吃饭
    12 李斯:汇报完毕...
    13 王斯:观察到韩非子活动,自己也开始活动了...
    14 王斯:因为韩非子在吃饭,所以我悲伤啊
    15 王斯:哭死了...
    16 韩非子:开始娱乐了...
    17 李斯:观察到韩非子活动,开始向秦老板汇报
    18 李斯:报告,秦老板,韩非子有活动了-->韩非子在娱乐
    19 李斯:汇报完毕...
    20 
    21 * Created            :     2017.07.13.
    22 * Author            :     Yu Weifeng
    23 * Function List         :     
    24 * Last Modified     :     
    25 * History            :     
    26 ******************************************************************************/
    27 #include"stdio.h"
    28 #include"malloc.h"
    29 #include"stdlib.h"
    30 #include"string.h"
    31 #include"ObserverPattern.h"
    32 
    33 
    34 
    35 
    36 /*****************************************************************************
    37 -Fuction        : main
    38 -Description    : 
    39 -Input            : 
    40 -Output         : 
    41 -Return         : 
    42 * Modify Date      Version         Author           Modification
    43 * -----------------------------------------------
    44 * 2017/07/13    V1.0.0         Yu Weifeng       Created
    45 ******************************************************************************/
    46 int main(int argc,char **argv)
    47 {
    48     T_Observer Lisi=newLisiObserver;
    49     T_Observer Wangsi=newWangsiObserver;
    50     
    51     T_Observable tObserver=newHanfeiziObservable;
    52     T_Hanfeizi Hanfeizi=newHanfeizi(&tObserver);
    53 
    54     Hanfeizi.ptObservable->AddObserver(&Lisi);
    55     Hanfeizi.ptObservable->AddObserver(&Wangsi);
    56     Hanfeizi.HaveBreakfast();
    57 
    58     Hanfeizi.ptObservable->DeleteObserver(&Wangsi);
    59     Hanfeizi.HaveFun();
    60 
    61     
    62     return 0;
    63 }
    ObserverPatternUsage.c

    2)被调用者:

      1 /*****************************************************************************
      2 * Copyright (C) 2017-2018 Hanson Yu  All rights reserved.
      3 ------------------------------------------------------------------------------
      4 * File Module        :     ObserverPattern.c
      5 * Description        :     观察者模式
      6                         本文件是被观察者实现类
      7                         以韩非子的活动被李斯,王斯观察举例,显然
      8                         韩非子是被观察者
      9 * Created            :     2017.07.13.
     10 * Author            :     Yu Weifeng
     11 * Function List         :     
     12 * Last Modified     :     
     13 * History            :     
     14 ******************************************************************************/
     15 #include"stdio.h"
     16 #include"malloc.h"
     17 #include"stdlib.h"
     18 #include"string.h"
     19 #include"ObserverPattern.h"
     20 
     21 
     22 static T_Observer g_atObserver[MAX_OBSERVER_NUM]={NULL};
     23 static int g_iObserverLen=0;
     24 
     25 /*****************************************************************************
     26 -Fuction        : HanfeiziAddObserver
     27 -Description    : 公有函数
     28 -Input            : 
     29 -Output         : 
     30 -Return         : 
     31 * Modify Date      Version         Author           Modification
     32 * -----------------------------------------------
     33 * 2017/07/13      V1.0.0         Yu Weifeng       Created
     34 ******************************************************************************/
     35 int HanfeiziAddObserver(T_Observer *i_ptObserver)
     36 {
     37     int iRet=-1;
     38     if(g_iObserverLen>=MAX_OBSERVER_NUM)
     39     {
     40         printf("ObserverArray full!
    ");
     41         iRet=-1;
     42     }
     43     else
     44     {
     45         memcpy(&g_atObserver[g_iObserverLen],i_ptObserver,sizeof(T_Observer));
     46         g_iObserverLen++;
     47         //printf("ObserverLen:%d
    ",g_iObserverLen);
     48         iRet=0;
     49     }
     50     return iRet;
     51 }
     52 /*****************************************************************************
     53 -Fuction        : HanfeiziAddObserver
     54 -Description    : 公有函数
     55 -Input            : 
     56 -Output         : 
     57 -Return         : 
     58 * Modify Date      Version         Author           Modification
     59 * -----------------------------------------------
     60 * 2017/07/13      V1.0.0         Yu Weifeng       Created
     61 ******************************************************************************/
     62 int HanfeiziDeleteObserver(T_Observer *i_ptObserver)
     63 {
     64     int iRet=-1;
     65     int i;
     66     if(g_iObserverLen==0)
     67     {
     68         printf("ObserverArray empty!
    ");
     69         iRet=-1;
     70     }
     71     else
     72     {
     73         for(i=0;i<g_iObserverLen;i++)
     74         {
     75             if(0==memcmp(&g_atObserver[i],i_ptObserver,sizeof(T_Observer)))
     76             {
     77                 break;
     78             }
     79             else
     80             {
     81             }
     82         }
     83         if(i>=g_iObserverLen)
     84         {
     85             printf("HanfeiziDeleteObserver err!
    ");
     86             iRet=-1;
     87         }
     88         else
     89         {
     90             for(;i<g_iObserverLen-1;i++)
     91             {
     92                 memcpy(&g_atObserver[i],&g_atObserver[i+1],sizeof(T_Observer));
     93             }
     94             g_iObserverLen--;
     95             iRet=0;
     96         }
     97     }
     98     return iRet;
     99 }
    100 
    101 /*****************************************************************************
    102 -Fuction        : HanfeiziNotifyObservers
    103 -Description    : 公有函数
    104 -Input            : 
    105 -Output         : 
    106 -Return         : 
    107 * Modify Date      Version         Author           Modification
    108 * -----------------------------------------------
    109 * 2017/07/13      V1.0.0         Yu Weifeng       Created
    110 ******************************************************************************/
    111 void HanfeiziNotifyObservers(char *i_strContext)
    112 {
    113     int i;
    114     for(i=0;i<g_iObserverLen;i++)
    115     {//通知所有观察这
    116         g_atObserver[i].Update(i_strContext);
    117     }
    118 }
    119 
    120 
    121 /*****************************************************************************
    122 -Fuction        : HanfeiziHaveBreakfast
    123 -Description    : 公有函数
    124 -Input            : 
    125 -Output         : 
    126 -Return         : 
    127 * Modify Date      Version         Author           Modification
    128 * -----------------------------------------------
    129 * 2017/07/13      V1.0.0         Yu Weifeng       Created
    130 ******************************************************************************/
    131 void HanfeiziHaveBreakfast()
    132 {
    133     printf("韩非子:开始吃饭...
    ");
    134     //通知所有观察者
    135     HanfeiziNotifyObservers("韩非子在吃饭");
    136 }
    137 
    138 /*****************************************************************************
    139 -Fuction        : HanfeiziHaveFun
    140 -Description    : 公有函数
    141 -Input            : 
    142 -Output         : 
    143 -Return         : 
    144 * Modify Date      Version         Author           Modification
    145 * -----------------------------------------------
    146 * 2017/07/13      V1.0.0         Yu Weifeng       Created
    147 ******************************************************************************/
    148 void HanfeiziHaveFun()
    149 {
    150     printf("韩非子:开始娱乐了...
    ");
    151     //通知所有观察者
    152     HanfeiziNotifyObservers("韩非子在娱乐");
    153 }
    ObserverPattern.c
     1 /*****************************************************************************
     2 * Copyright (C) 2017-2018 Hanson Yu  All rights reserved.
     3 ------------------------------------------------------------------------------
     4 * File Module        :     ObserverPattern.h
     5 * Description        :     观察者模式
     6                                     
     7 * Created            :     2017.07.13.
     8 * Author            :     Yu Weifeng
     9 * Function List         :     
    10 * Last Modified     :     
    11 * History            :     
    12 ******************************************************************************/
    13 #ifndef OBSERVER_PATTERN_H
    14 #define OBSERVER_PATTERN_H
    15 
    16 #define MAX_OBSERVER_NUM    5
    17 typedef struct Observer
    18 {
    19     void (*Update)(char *i_strContext);
    20 }T_Observer;//抽象出观察者
    21 
    22 typedef struct Observable
    23 {
    24     int (*AddObserver)(T_Observer *i_ptObserver);//传参,接口,也就是抽象耦合
    25     int (*DeleteObserver)(T_Observer *i_ptObserver);
    26     void (*NotifyObservers)(char *i_strContext);
    27 }T_Observable;//抽象出被观察者
    28 
    29 typedef struct Hanfeizi//C的局限,使用继承(覆写)代替实现两个接口更好
    30 {//(少定义一个实现类,封装性也更好)
    31     T_Observable *ptObservable;
    32     void (*HaveBreakfast)();
    33     void (*HaveFun)();
    34 }T_Hanfeizi;
    35 
    36 
    37 int HanfeiziAddObserver(T_Observer *i_ptObserver);
    38 int HanfeiziDeleteObserver(T_Observer *i_ptObserver);
    39 void HanfeiziNotifyObservers(char *i_strContext);
    40 void HanfeiziHaveBreakfast();
    41 void HanfeiziHaveFun();
    42 #define newHanfeiziObservable {HanfeiziAddObserver,HanfeiziDeleteObserver,HanfeiziNotifyObservers}
    43 #define newHanfeizi(Observable) {Observable,HanfeiziHaveBreakfast,HanfeiziHaveFun}
    44 
    45 
    46 void LisiUpdate(char *i_strContext);
    47 #define newLisiObserver {LisiUpdate}
    48 
    49 void WangsiUpdate(char *i_strContext);
    50 #define newWangsiObserver {WangsiUpdate}
    51 
    52 
    53 #endif
    ObserverPattern.h
     1 /*****************************************************************************
     2 * Copyright (C) 2017-2018 Hanson Yu  All rights reserved.
     3 ------------------------------------------------------------------------------
     4 * File Module        :     ObserverLisi.c
     5 * Description        :     观察者李斯
     6                         本文件是观察者实现类李斯的动作
     7 * Created            :     2017.07.13.
     8 * Author            :     Yu Weifeng
     9 * Function List         :     
    10 * Last Modified     :     
    11 * History            :     
    12 ******************************************************************************/
    13 #include"stdio.h"
    14 #include"malloc.h"
    15 #include"stdlib.h"
    16 #include"string.h"
    17 #include"ObserverPattern.h"
    18 
    19 /*****************************************************************************
    20 -Fuction        : LisiReportToQinshihuang
    21 -Description    : 私有函数
    22 -Input            : 
    23 -Output         : 
    24 -Return         : 
    25 * Modify Date      Version         Author           Modification
    26 * -----------------------------------------------
    27 * 2017/07/13      V1.0.0         Yu Weifeng       Created
    28 ******************************************************************************/
    29 static void LisiReportToQinshihuang(char *i_strContext)
    30 {
    31     printf("李斯:报告,秦老板,韩非子有活动了-->%s
    ",i_strContext);
    32 }
    33 
    34 /*****************************************************************************
    35 -Fuction        : LisiUpdate
    36 -Description    : 公有函数
    37 -Input            : 
    38 -Output         : 
    39 -Return         : 
    40 * Modify Date      Version         Author           Modification
    41 * -----------------------------------------------
    42 * 2017/07/13      V1.0.0         Yu Weifeng       Created
    43 ******************************************************************************/
    44 void LisiUpdate(char *i_strContext)
    45 {
    46     printf("李斯:观察到韩非子活动,开始向秦老板汇报
    ");
    47     LisiReportToQinshihuang(i_strContext);
    48     printf("李斯:汇报完毕...
    ");
    49 }
    ObserverLisi.c
     1 /*****************************************************************************
     2 * Copyright (C) 2017-2018 Hanson Yu  All rights reserved.
     3 ------------------------------------------------------------------------------
     4 * File Module        :     ObserverWangsi.c
     5 * Description        :     观察者王斯
     6                         本文件是观察者实现类王斯的动作
     7 * Created            :     2017.07.13.
     8 * Author            :     Yu Weifeng
     9 * Function List         :     
    10 * Last Modified     :     
    11 * History            :     
    12 ******************************************************************************/
    13 #include"stdio.h"
    14 #include"malloc.h"
    15 #include"stdlib.h"
    16 #include"string.h"
    17 #include"ObserverPattern.h"
    18 
    19 /*****************************************************************************
    20 -Fuction        : WangsiCry
    21 -Description    : 私有函数
    22 -Input            : 
    23 -Output         : 
    24 -Return         : 
    25 * Modify Date      Version         Author           Modification
    26 * -----------------------------------------------
    27 * 2017/07/13      V1.0.0         Yu Weifeng       Created
    28 ******************************************************************************/
    29 static void WangsiCry(char *i_strContext)
    30 {
    31     printf("王斯:因为%s,所以我悲伤啊
    ",i_strContext);
    32 }
    33 
    34 /*****************************************************************************
    35 -Fuction        : WangsiUpdate
    36 -Description    : 公有函数
    37 -Input            : 
    38 -Output         : 
    39 -Return         : 
    40 * Modify Date      Version         Author           Modification
    41 * -----------------------------------------------
    42 * 2017/07/13      V1.0.0         Yu Weifeng       Created
    43 ******************************************************************************/
    44 void WangsiUpdate(char *i_strContext)
    45 {
    46     printf("王斯:观察到韩非子活动,自己也开始活动了...
    ");
    47     WangsiCry(i_strContext);
    48     printf("王斯:哭死了...
    ");
    49 }
    ObserverWangsi.c

    3)执行结果:

    book@book-desktop:/work/projects/test/DesignPatterns/ObserverPattern$ gcc -o ObserverPatternUsage

    ObserverLisi.c  ObserverWangsi.c  ObserverPattern.c ObserverPatternUsage.c

    book@book-desktop:/work/projects/test/DesignPatterns/ObserverPattern$ ./ObserverPatternUsage

    韩非子:开始吃饭...

    李斯:观察到韩非子活动,开始向秦老板汇报

    李斯:报告,秦老板,韩非子有活动了-->韩非子在吃饭

    李斯:汇报完毕...

    王斯:观察到韩非子活动,自己也开始活动了...

    王斯:因为韩非子在吃饭,所以我悲伤啊

    王斯:哭死了...

    韩非子:开始娱乐了...

    李斯:观察到韩非子活动,开始向秦老板汇报

    李斯:报告,秦老板,韩非子有活动了-->韩非子在娱乐

    李斯:汇报完毕...

    4)详细代码:

    https://github.com/fengweiyu/DesignThinking/tree/master/DesignPatterns/BehavioralDesignPatterns/ObserverPattern

    三、使用场景

    1.关联行为场景,

    需要注意的是,关联行为是可拆分的,而不是"组合"关系

    2.时间多级触发场景

    3.跨系统的消息交换场景,如消息队列的处理机制

    4.一个地方监视另外一个地方的处理情况,但又不想让监视方与被监视方之间相互依赖的时候

    四、优点

    1.观察者和被观察者之间是抽象耦合

    2.建立了一套触发机制

    五、缺点

    1.一个被观察者,多个观察者,开发和调试就会比较复杂,在这种情况下,一般考虑采用异步的方式(考虑线程安全和队列的问题)。

    多级触发时的效率更是让人担忧,大家在设计时注意考虑。

    2.一个被观察者,多个观察者,观察者如何快速响应问题,两个办法:

    1)采用多线程技术,

    无论是被观察者启动线程还是观察者启动线程,都可以跳高系统性能,这也就是大家通常说的异步架构

    2)缓存技术,

    即准备好足够的资源,以保证快速响应,代价就是开发难度大,压力测试要足够充分,这种方法也就是大家说的同步架构

    2.广播链问题

    一个观察者可以有双重身份,既是观察者也是被观察者,这就会形成一个触发链。这样逻辑就比较复杂,可维护性非常差,在一个观察者模式中最多出现一个对象既是观察者也是被观察者,也就是说消息最多转发一次(传递两次)才比较好控制。

    注意:它和责任链模式最大的区别是,观察者模式是相邻两个结点结构,即处理完返回时也是返回到上一个结点。而责任链处理完后可以直接返回到最初的结点即根节点。

  • 相关阅读:
    Web下的HTTPS应用
    laravel用crud之index列出产品items
    laravel用crud修改产品items-新建resource controller和routing
    用laravel dingo/api创建产品api
    用laravel dingo/api创建简单的api
    composer错误提示Cloning failed using an ssh key for authentication的解决方法
    防止SQL注入的6个要点
    magento 2.3安装测试数据
    教你一步步composer安装Magento2.3
    30个redis.conf 配置项说明
  • 原文地址:https://www.cnblogs.com/yuweifeng/p/7171477.html
Copyright © 2020-2023  润新知