一颗不安分的创业心

DOTA版设计模式——观察者

观察者在生活中最显而易见的例子就是报纸订阅了,此时报纸内容是主体,而每个花钱订阅的家庭就都是观察者。
当你订阅时报纸出版商会将报纸按时发到你的订报箱,当你停止订阅是你的订报箱将会是空的,当然你随时可以订阅或取消订阅。
UML图:

观察者模式对主题信息的处理方式分两种,“推模式”和“拉模式”。framework中最明显的观察者模式要算是事件了,你可以使用“+=”来添加观察者,也可以用“-=”来取消观察者,而时间的两个参数“sender”和“eventarg”要算是推模式和拉模式的结合了。
比如btnXXX_Click(object sender,EventArg e),是事件的形式。
1)其中推模式传递的参数是EventArg e,里边的内容是有限的,包含主题想让观察者知道的东西,有利于控制观察者得到的信息。但是有一个问题是,如果主题新加了内容,比如新加了“成人板块”,然而EventArg中并没有“成人板块”,现在就不得不在两个地方添加“成人板块”,一个是主题,一个是EventArg类。
2)而拉模式不是主题主动传值给观察者,而是将自己本身传递个观察者,此时如果主题发生了变化,只要更改主题类即可,别的地方不用修改,在例子中主题就是我们的object sender。
3)两种模式的观察者各有利弊可以根据项目实际需求选择适合的观察者模式。
如果选择主题(button)主动传来的值(推模式):
则:e.YYYY(遗憾的是button的EventArg什么都没传)。
如果直接操作主题(button)(拉模式),则:
Button button as sender;
if(button != null)
{
         //得到button的任意值,比如button.Text。当然这一切建立在button作为sender传递过来
}
本例中只要主题实现了ISubject接口,观察者实现了IObserver接口即可,详细见完整代码:
    public interface ISubject
    {
        
void AddObserver(IObserver observer);//添加观察者
        
void RemoveObserver(IObserver observer);//移除观察者
        
void NotifyObserver();//通知所有观察者
        ParamValue GetParamValue();
    }

    public interface IObserver
    {
        
void Update(ISubject subject, ParamValue paramValue);//观察者接到通知后处理工作
    }

完整代码:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections;

using DotaCommon;

namespace DotaPatternLibrary.Observer
{
    
public interface ISubject
    {
        
void AddObserver(IObserver observer);
        
void RemoveObserver(IObserver observer);
        
void NotifyObserver();
        ParamValue GetParamValue();
    }

    
public interface IObserver
    {
        
void Update(ISubject subject, ParamValue paramValue);
    }

    
public class ParamValue
    {
        
private string _messageValue;

        
public string MessageValue
        {
            
get { return _messageValue; }
            
set { _messageValue = value; }
        }
    }

    
public class Game : ISubject
    {
        
#region ISubject 成员

        
public void AddObserver(IObserver observer)
        {
            observers.Add(observer);
        }

        
public void RemoveObserver(IObserver observer)
        {
            observers.Remove(observer);
        }

        
public void NotifyObserver()
        {
            
foreach (IObserver observer in observers.ToArray(typeof(IObserver)))
            {
                observer.Update(
this, _paramValue);
            }
        }

        
public ParamValue GetParamValue()
        {
            
return _paramValue;
        }

        
#endregion

        
private ArrayList observers;
        
private ParamValue _paramValue;
        
public Game()
        {
            observers 
= new ArrayList();
            _paramValue 
= new ParamValue();
        }

        
public ParamValue PV
        {
            
set { _paramValue = value; }
        }
    }

    
public class GamePlayerOne : IObserver
    {
        
#region IObserver 成员

        
public void Update(ISubject subject, ParamValue paramValue)
        {
            LandpyForm.Form.OutputResult(
"gamerone(Push Model):" + paramValue.MessageValue);
            
//subject可为抽象类得到的值不用函数返回
            LandpyForm.Form.OutputResult("gamerone(Pull Model):" + subject.GetParamValue().MessageValue);
        }

        
#endregion

        
public GamePlayerOne(ISubject subject)
        {
            subject.AddObserver(
this);
        }

        
public void OutOfSubject(ISubject subject)
        {
            subject.RemoveObserver(
this);
        }
    }

    
public class GamePlayerTwo : IObserver
    {
        
#region IObserver 成员

        
public void Update(ISubject subject, ParamValue paramValue)
        {
            LandpyForm.Form.OutputResult(
"gamertwo(Push Model):" + paramValue.MessageValue);
            
//subject可为抽象类得到的值不用函数返回
            LandpyForm.Form.OutputResult("gamertwo(Pull Model):" + subject.GetParamValue().MessageValue);
        }

        
#endregion

        
public GamePlayerTwo(ISubject subject)
        {
            subject.AddObserver(
this);
        }

        
public void OutOfSubject(ISubject subject)
        {
            subject.RemoveObserver(
this);
        }
    }
}
posted @ 2009-07-26 23:01  pangxiaoliang[北京]流浪者  阅读(337)  评论(0编辑  收藏  举报
小豆芽之父