观察者模式

百度百科:https://baike.baidu.com/item/%E8%A7%82%E5%AF%9F%E8%80%85%E6%A8%A1%E5%BC%8F/5881786?fr=aladdin

观察者模式

观察者模式(有时又被称为模型-视图(View)模式、源-收听者(Listener)模式或从属者模式)是 软件设计模式的一种。在此种模式中,一个目标物件管理所有相依于它的观察者物件,并且在它本身的状态改变时主动发出通知。这通常透过呼叫各观察者所提供的方法来实现。此种模式通常被用来实现事件处理系统。
 

基本简介

编辑
观察者模式(Observer)完美的将观察者和被观察的对象分离开。举个例子,用户界面可以作为一个观察者,业务数据是被观察者,用户界面观察业务数据的变化,发现数据变化后,就显示在界面上。 面向对象设计的一个原则是:系统中的每个类将重点放在某一个功能上,而不是其他方面。一个对象只做一件事情,并且将他做好。观察者模式在模块之间划定了清晰的界限,提高了应用程序的可维护性和重用性。
观察者设计模式定义了对象间的一种一对多的组合关系,以便一个对象的状态发生变化时,所有依赖于它的对象都得到通知并自动刷新。
 

实现方式

编辑
观察者模式有很多实现方式,从根本上说,该模式必须包含两个角色:观察者和被观察对象。在刚才的例子中, 业务数据是被观察对象,用户界面是观察者。观察者和被观察者之间存在“观察”的逻辑关联,当被观察者发生改变的时候,观察者就会观察到这样的变化,并且做出相应的响应。如果在用户界面、业务数据之间使用这样的观察过程,可以确保界面和数据之间划清界限,假定应用程序的需求发生变化,需要修改界面的表现,只需要重新构建一个用户界面,业务数据不需要发生变化。
 

“观察”

编辑
实现观察者模式的时候要注意,观察者和被观察对象之间的互动关系不能体现成类之间的直接调用,否则就将使观察者和被观察对象之间紧密的耦合起来,从根本上违反 面向对象的设计的原则。无论是观察者“观察”观察对象,还是被观察者将自己的改变“通知”观察者,都不应该直接调用。

过程

编辑
实现观察者模式有很多形式,比较直观的一种是使用一种“注册——通知——撤销注册”的形式。下面的三个图详细的描述了这样一种过程:
 

观察者

(Observer)将自己注册到被观察对象(Subject)中,被观察对象将观察者存放在一个容器(Container)里。
 

被观察

被观察对象发生了某种变化(如图中的SomeChange),从容器中得到所有注册过的观察者,将变化通知观察者。
 

撤销观察

观察者告诉被观察者要撤销观察,被观察者从容器中将观察者去除。
观察者将自己注册到被观察者的容器中时,被观察者不应该过问观察者的具体类型,而是应该使用观察者的接口。这样的优点是:假定程序中还有别的观察者,那么只要这个观察者也是相同的接口实现即可。一个被观察者可以对应多个观察者,当被观察者发生变化的时候,他可以将消息一一通知给所有的观察者。基于接口,而不是具体的实现——这一点为程序提供了更大的灵活性。
 

例子

编辑
 

Java代码Demo

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
//观察者,需要用到观察者模式的类需实现此接口
public  interface  Observer{
     void  update(Object...objs);
}
 
//被观察者(一个抽象类,方便扩展)
public  abstract  class  Observable{
 
     public  final  ArrayList<Class<?>> obserList =  new  ArrayList<Class<?>>();
 
     /**AttachObserver(通过实例注册观察者)
     *<b>Notice:</b>obcan'tbenull,oritwillthrowNullPointerException
     **/
     public <T>  void  registerObserver(T ob){
         if (ob== null throw  new  NullPointerException();
         this .registerObserver(ob.getClass());
     }
 
     /**
     *AttachObserver(通过Class注册观察者)
     *@paramcls
     */
     public  void  registerObserver(Class<?> cls){
         if (cls== null throw  new  NullPointerException();
         synchronized (obserList){
             if (!obserList.contains(cls)){
                 obserList.add(cls);
             }
         }
     }
 
     /**UnattachObserver(注销观察者)
     *<b>Notice:</b>
     *<b>ItreverseswithattachObserver()method</b>
     **/
     public <T> void  unRegisterObserver(Tob){
         if (ob== null throw  new  NullPointerException();
         this .unRegisterObserver(ob.getClass());
     }
 
     /**UnattachObserver(注销观察者,有时候在未获取到实例使用)
     *<b>Notice:</b>
     *<b>ItreverseswithattachObserver()method</b>
     **/
     public  void  unRegisterObserver(Class<?>cls){
         if (cls== null throw  new  NullPointerException();
         synchronized (obserList){
             Iterator<Class<?>>iterator=obserList.iterator();
             while (iterator.hasNext()){
                 if (iterator.next().getName().equals(cls.getName())){
                     iterator.remove();
                     break ;
                 }
             }
         }
     }
 
     /**detachallobservers*/
     public  void  unRegisterAll(){
         synchronized (obserList){
             obserList.clear();
         }
     }
 
     /**Ruturnthesizeofobservers*/
     public  int  countObservers(){
         synchronized (obserList){
             returnobserList.size();
         }
     }
 
     /**
     *notify all observer(通知所有观察者,在子类中实现)
     *@paramobjs
     */
     public  abstract  void  notifyObservers(Object... objs);
 
     /**
     *notify one certain observer(通知某一个确定的观察者)
     *@paramcls
     *@paramobjs
     */
     public  abstract  void  notifyObserver(Class<?> cls, Object... objs);
 
     /**
     *notifyonecertainobserver
     *@paramcls
     *@paramobjs
     */
     public  abstract <T>  void  notifyObserver(T t, Object... objs);
}
 
//目标被观察者
public  class  ConcreteObservable  extends  Observable{
 
     private  static  ConcreteObservableinstance =  null ;
     private  ConcreteObservable(){};
     public  static  synchronized  ConcreteObservablegetInstance(){
         if (instance ==  null ){
             instance=newConcreteObservable();
         }
         returninstance;
     }
 
     @Override
     public  <T>  void  notifyObserver(T t, Object... objs){
         if (t ==  null throw  new  NullPointerException();
         this .notifyObserver(t.getClass(), objs);
     }
 
     @Override
     public  void  notifyObservers(Object... objs){
         for (Class<?>cls : obserList){
             this .notifyObserver(cls, objs);
         }
     }
 
 
     //通过java反射机制实现调用
     @Override
     public  void  notifyObserver(Class<?>cls, Object...objs){
         if (cls ==  null throw  new  NullPointerException();
         Method[] methods = cls.getDeclaredMethods();
         for (Method method : methods){
             if (method.getName().equals( "update" )){
                 try {
                     method.invoke(cls,objs);
                     break ;
                 } catch (IllegalArgumentException e){
                     e.printStackTrace();
                 } catch (IllegalAccessException e){
                     e.printStackTrace();
                 } catch (InvocationTargetException e){
                     e.printStackTrace();
                 }
             }
         }
     }
}
 
//使用(实现Observer接口)
public  class  Text  extends  Activity  implements  Observer{
     publicvoidonCreate(...){
         ConcreteObservable.getInstance().registerObserver(Text. class );
         ....
     }
 
     //实现接口处理
     publicvoidupdate(Object...objs){
         //做操作,比如更新数据,更新UI等
     }
}
 

php代码DEMO

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
<?php
class  car  implements  SplSubject
{
     //车的类型
     private  $carName ;
     //车的状态,0为关闭,1这启动车子
     private  $carState  = 0;
     //初始化车的速度表值
     private  $carSpeed  = 0;
     //各项车的性能观察对象
     private  $Observers ;
     public  function  __construct( $Name )
     {
         $this ->carName   =  $Name ;
         $this ->Observers =  new  SplObjectStorage;
     }
     //启动
     public  function  start()
     {
         $this ->carState = 1;
         $this ->notify();
     }
     //停车
     public  function  stop()
     {
         $this ->carState = 0;
         $this ->carSpeed = 0;
         $this ->notify();
     }
     //加速
     public  function  accelerate( $Acceleration )
     {
         if  (0 ===  $this ->carState) {
             throw  new  Exception( '先踩油门,不然车怎走啊!!!' );
         }
         if  (! is_int ( $Acceleration ) ||  $Acceleration  < 0) {
             throw  new  Exception( '加速值错了啊' );
         }
         $this ->carSpeed +=  $Acceleration ;
         $this ->notify();
     }
     //增加监测对象
     public  function  attach(SplObserver  $observer )
     {
         if  (! $this ->Observers->contains( $observer )) {
             $this ->Observers->attach( $observer );
         }
         return  true;
     }
     //删除监测对象
     public  function  detach(SplObserver  $observer )
     {
         if  (! $this ->Observers->contains( $observer )) {
             return  false;
         }
         $this ->Observers->detach( $observer );
         return  true;
     }
     //传送对象
     public  function  notify()
     {
         foreach  ( $this ->Observers  as  $observer ) {
             $observer ->update( $this );
         }
     }
     public  function  __get( $Prop )
     {
         switch  ( $Prop ) {
             case  'STATE' :
                 return  $this ->carState;
                 break ;
             case  'SPEED' :
                 return  $this ->carSpeed;
                 break ;
             case  'NAME' :
                 return  $this ->carName;
                 break ;
             default :
                 throw  new  Exception( $Prop  'cannotberead' );
         }
     }
     public  function  __set( $Prop $Val )
     {
         throw  new  Exception( $Prop  'cannotbeset' );
     }
}
 
class  carStateObserver  implements  SplObserver
{
     private  $SubjectState ;
     public  function  update(SplSubject  $subject )
     {
         switch  ( $subject ->STATE) {
             case  0:
                 if  ( is_null ( $this ->SubjectState)) {
                     echo  $subject ->NAME .  '没有启动呢'  "\t" ;
                 else  {
                     echo  $subject ->NAME .  '熄火了'  "\t" ;
                 }
                 $this ->SubjectState = 0;
                 break ;
             case  1:
                 if  (1 !==  $this ->SubjectState) {
                     echo  $subject ->NAME .  '启动了'  "\t" ;
                     $this ->SubjectState = 1;
                 }
                 break ;
             default :
                 throw  new  Exception( 'UnexpectederrorincarStateObserver::update()' );
         }
     }
}
 
class  carSpeedObserver  implements  SplObserver
{
     public  function  update(SplSubject  $subject )
     {
         if  (0 !==  $subject ->STATE) {
             echo  $subject ->NAME .  '目前速度为'  $subject ->SPEED .  'Kmh'  "\t" ;
         }
     }
}
 
class  carOverspeedObserver  implements  SplObserver
{
     public  function  update(SplSubject  $subject )
     {
         if  ( $subject ->SPEED > 130) {
             throw  new  Exception( '加速限制在130以内,你违规了!'  "\t" );
         }
     }
}
try  {
     $driver        new   car( 'AUDIA4' );
     $driverObserver1   new  carStateObserver;
     $driverObserver2   new  carSpeedObserver;
     $drivesrObserver3  new  carOverspeedObserver;
     $driver ->attach( $driverObserver1 );
     $driver ->attach( $driverObserver2 );
     $driver ->attach( $drivesrObserver3 );
     $driver ->start();
     $driver ->accelerate(10);
     $driver ->accelerate(30);
     $driver ->stop();
     $driver ->start();
     $driver ->accelerate(50);
     $driver ->accelerate(70);
     $driver ->accelerate(100);
     $driver ->accelerate(150);
}
catch  (Exception  $e ) {
     echo  $e ->getMessage();
}
?>
 

C++ 观察者模式例子

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
//filename observer.h
#include <iostream>
#include <set>
#include <string>
using  namespace  std;
/抽象模式定义
class  CObservable;
//观察者,纯虚基类
class  CObserver
{
public :
     CObserver(){};
     virtual  ~CObserver(){};
     //当被观察的目标发生变化时,通知调用该方法
     //来自被观察者pObs, 扩展参数为pArg
     virtual  void  Update(CObservable* pObs,  void * pArg = NULL) = 0;
};
//被观察者,即Subject
class  CObservable
{
public :
     CObservable() : m_bChanged( false ) {};
     virtual  ~CObservable() {};
     void  Attach(CObserver* pObs);    //注册观察者
     void  Detach(CObserver* pObs);    //注销观察者
     void  DetachAll();                //注销所有观察者
     void  Notify( void * pArg = NULL);  //若状态变化,则遍历观察者,逐个通知更新
     bool  HasChanged();               //测试目标状态是否变化
     int  GetObserversCount();         //获取观察者数量
protected :
     void  SetChanged();               //设置状态变化!!!必须继承CObservable才能设置目标状态
     void  ClearChanged();             //初始化目标为未变化状态
private :
     bool  m_bChanged;                 //状态
     set<CObserver*> m_setObs;        //set保证目标唯一性
};
/抽象模式实现
void  CObservable::Attach(CObserver* pObs){
     if  (!pObs)  return ;
     m_setObs.insert(pObs);
}
void  CObservable::Detach(CObserver* pObs){
     if  (!pObs)  return ;
     m_setObs.erase(pObs);
}
void  CObservable::DetachAll(){
     m_setObs.clear();
}
void  CObservable::SetChanged(){
     m_bChanged =  true ;
}
void  CObservable::ClearChanged(){
     m_bChanged =  false ;
}
bool  CObservable::HasChanged(){
     return  m_bChanged;
}
int  CObservable::GetObserversCount(){
     return  m_setObs.size();
}
void  CObservable::Notify( void * pArg  /* = NULL */ ){
     if  (!HasChanged())  return ;
     cout <<  "notify observers…"  << endl;
     ClearChanged();
     set<CObserver*>::iterator itr = m_setObs.begin();
     for  (; itr != m_setObs.end(); itr++){
         (*itr)->Update( this , pArg);
     }
}
/具体应用类定义和实现
//bloger是发布者,即被观察者(subject)
class  CBloger :  public  CObservable
{
public :
     void  Publish( const  string &strContent){
         cout <<  "bloger publish, content: "  << strContent << endl;
         SetChanged();
         Notify( const_cast < char *>(strContent.c_str()));
     }
};
//portal是发布者,即被观察者(subject)
class  CPortal :  public  CObservable
{
public :
     void  Publish( const  string &strContent){
         cout <<  "portal publish, content: "  << strContent << endl;
         SetChanged();
         Notify( const_cast < char *>(strContent.c_str()));
     }
};
//RSS阅读器,观察者
class  CRSSReader :  public  CObserver
{
public :
     CRSSReader( const  string &strName) : m_strName(strName){}
     virtual  void  Update(CObservable* pObs,  void * pArg = NULL){
         char * pContent =  static_cast < char *>(pArg);
         //观察多个目标
         if  ( dynamic_cast <CBloger*>(pObs)){
             cout << m_strName <<  " updated from bloger, content: "  << pContent << endl;
         } else  if  ( dynamic_cast <CPortal*>(pObs)){
             cout << m_strName <<  " updated from portal, content: "  << pContent << endl;
         }
     }
private :
     string m_strName;
};
//Mail阅读器,观察者
class  CMailReader :  public  CObserver
{
public :
     CMailReader( const  string &strName) : m_strName(strName){}
     virtual  void  Update(CObservable* pObs,  void * pArg = NULL){
             char * pContent =  static_cast < char *>(pArg);
             if  ( dynamic_cast <CBloger*>(pObs)){
                 cout << m_strName <<  " updated from bloger, content: "  << pContent << endl;
             }
             if  ( dynamic_cast <CPortal*>(pObs)){
                 cout << m_strName <<  " updated from portal, content: "  << pContent << endl;
             }
         }
private :
     string m_strName;
};
#include "observer.h"
int  main()
{
                                   //目标(被观察者)
     CBloger* pBloger =  new  CBloger();
     CPortal* pPortal =  new  CPortal();
                                   //观察者. 一个观察者可以观察多个目标
     CRSSReader* pRssReader =  new  CRSSReader( "rss reader" );
     CMailReader* pMailReader =  new  CMailReader( "mail reader" );
     pBloger->Attach(pRssReader);   //bloger注册观察者
     pBloger->Attach(pMailReader);  //bloger注册观察者
     pPortal->Attach(pRssReader);   //portal注册观察者
     pPortal->Attach(pMailReader);  //portal注册观察者
                                   //博客发布信息
     pBloger->Publish( "博客分享设计模式" );
     cout << endl;
                                   //门户发布信息
     pPortal->Publish( "门户分享设计模式" );
     cout <<  "\nportal detached mail reader"  << endl;
     
     pPortal->Detach(pMailReader);
     
     cout <<  "portal observers count: "  << pPortal->GetObserversCount() << endl << endl;
     pPortal->Publish( "门户分享设计模式" );
     
     system ( "pause" );
     return  0;
}

转载于:https://www.cnblogs.com/amwuau/p/8665627.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值