使用范型观察者模式观察多个数据的实现

 观察者模式是最灵活、最多变的一种模式。在现实开发中,我常常会遇到观察者很多而且观察的数据也各不相同的情况,如果采用经典的观察者实现方法,在观察者的Update方法中难免要传递Subject中自己并不关心的数据,为此我采用了另外一种实现方式,希望和各位共同探讨。
范型观察者接口

 1 ExpandedBlockStart.gif ContractedBlock.gif interface  IObserver < DT >   dot.gif {
 2ExpandedSubBlockStart.gifContractedSubBlock.gif        /**//// <summary>
 3InBlock.gif        /// 观察和监视的数据
 4ExpandedSubBlockEnd.gif        /// </summary>

 5ExpandedSubBlockStart.gifContractedSubBlock.gif        DT ObserverSubject dot.gifget;set;}
 6InBlock.gif
 7ExpandedSubBlockStart.gifContractedSubBlock.gif        /**//// <summary>
 8InBlock.gif        /// 响应
 9ExpandedSubBlockEnd.gif        /// </summary>

10InBlock.gif        void Respond();
11ExpandedBlockEnd.gif    }
其中ObserverSubject是所要关心的数据,实现这个接口的具体类,必须指明它所关系的数据对象。
例如:
ExpandedBlockStart.gif ContractedBlock.gif   class  ObserverUI :IObserver < UIData > dot.gif {
InBlock.gif
ContractedSubBlock.gifExpandedSubBlockStart.gif        
IObserver Members#region IObserver<UIData> Members
InBlock.gif
InBlock.gif        
private UIData _data = new UIData();
ExpandedSubBlockStart.gifContractedSubBlock.gif        
public UIData ObserverSubject dot.gif{
ExpandedSubBlockStart.gifContractedSubBlock.gif            
get dot.gif{
InBlock.gif                
return _data;
ExpandedSubBlockEnd.gif            }

ExpandedSubBlockStart.gifContractedSubBlock.gif            
set dot.gif{
InBlock.gif                _data 
= value;
ExpandedSubBlockEnd.gif            }

ExpandedSubBlockEnd.gif        }

InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif        
public void Respond() dot.gif{
InBlock.gif            Console.WriteLine(
this.ObserverSubject.Value.ToString());
ExpandedSubBlockEnd.gif        }

InBlock.gif
ExpandedSubBlockEnd.gif        
#endregion

ExpandedBlockEnd.gif    }

其中UIData对象是存储界面数据的,UI观察者所关心的数据也就是UIData类型,如果给它Log类型的数据就是浪费。
下面来关注一下Subject,因为这里面观察的数据是多种多样的,就是把关心的数据放在一起还是分散开来呢?哪一种更有利于扩展呢?这个问题我也曾经苦恼过,最后决定把所关心的数据分离开来,并使用委托的方式来实现通知观察者。
 1 None.gif   public   delegate   void  RespondHandler();
 2 ExpandedBlockStart.gifContractedBlock.gif     class  SubjectUI  dot.gif {
 3InBlock.gif        public event RespondHandler OnRespond;
 4InBlock.gif
 5InBlock.gif        private UIData _uiData = new UIData();
 6InBlock.gif
 7ExpandedSubBlockStart.gifContractedSubBlock.gif        public UIData UIdata dot.gif{
 8ExpandedSubBlockStart.gifContractedSubBlock.gif            get dot.gifreturn _uiData; }
 9ExpandedSubBlockStart.gifContractedSubBlock.gif            set dot.gif{ _uiData = value; }
10ExpandedSubBlockEnd.gif        }

11InBlock.gif
12ExpandedSubBlockStart.gifContractedSubBlock.gif        public void Notify() dot.gif{
13ExpandedSubBlockStart.gifContractedSubBlock.gif            if (OnRespond != nulldot.gif{
14InBlock.gif                OnRespond();
15ExpandedSubBlockEnd.gif            }

16ExpandedSubBlockEnd.gif        }

17InBlock.gif
18ExpandedBlockEnd.gif    }

从上面的代码中不难看出定义了一个OnRespond事件,使用了委托RespondHandler.在通知Notify方法中,他会激发注册事件。它本身不需要关心谁会被激发,从而表现的比较独立和灵活。

应用的时候,

1 None.gif uiObserver.ObserverSubject.Value  =   100 ;
2 None.gifsubUI.Notify();

注意上面两行代码UI观察者观察的数据被改动了,观察着的经典模式是通过事件参数或者是访问Subject中包含的数据。但是如果使用事件参数,导致如果增加一种观察的类型,事件参数就会变得很庞大,另外我曾经考虑过通过访问Subject中包含的类型作为通知的数据,但是自我感觉更习惯于从观察者自身所关心的数据进行修改,然后通知被观察的数据。
      由于本人刚刚接触设计模式没多久,可能很多地方考虑不妥,还请各位指点,共同切磋。

转载于:https://www.cnblogs.com/DreamWinter/articles/338360.html

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值