委托与事件

.net中委托与事件的编程规范:

1.委托的名称都应该以EventHandler结束

2.委托的原型定义:有一个void返回值.并接受两个输入参数:一个Object类型的参数,一个EventArgs类型(或继承自EventArgs)

3.事件的命名为 委托去掉EventHandler之后的部分

4.继承自EventArgs的类型应该以EventArgs结尾

说明:

1.委托中的Object类型的参数为引发事件的对象.

2.EventArgs对象应包含事件处理对象所需要的数据.

见下例,对下例该如何改造:

public class Heater
{
    public int temp=0;

    public event BoilHandler BoilEvent;
    public void BoilWater()
    {
        for (; temp <= 100; temp++)
        {
            if (temp >= 96)
            {
                if (BoilEvent != null)
                {
                    BoilEvent(temp);
                }
            }
        }
    }
}

public delegate void BoilHandler(int temp);
public class Alarm
{
    public void MakeAlert(int temp)
    {
        HttpContext.Current.Response.Write("警告:现在温度是" + temp.ToString() + "<br/>");
    }
}

public class Display
{
    public void ShowMsg(int temp)
    {
        HttpContext.Current.Response.Write("提示:水开了.温度是" + temp.ToString() + "<br/>");
    }
}

页面调用:

    protected void Page_Load(object sender, EventArgs e)
    {
        Heater heater = new Heater();
        Alarm alarm = new Alarm();
        Display display = new Display();

        heater.BoilEvent += alarm.MakeAlert;
        heater.BoilEvent += display.ShowMsg;
        heater.BoilWater();        
    }

若使用委托,按照编码规范,改造如下:

public class Heater
{
    public int temp;
    public Heater(int temp)
    {
        this.temp = temp;
    }

    public delegate void BoilEventHandler(Object sender,BoiledEventArgs e);
    public event BoilEventHandler Boil;

    public void BoilWater()
    {
        for (; temp <= 100; temp++)
        {
            if (temp >= 96)
            {
                BoiledEventArgs e = new BoiledEventArgs(temp);
                if (Boil != null)
                {
                    Boil(this, e);
                }
            }
        }
    }
}

public class BoiledEventArgs : EventArgs
{
    public int temp;
    public BoiledEventArgs(int temp)
    {
        this.temp = temp;
    }
}

public class Alarm
{
    public void MakeAlert(Object sender,BoiledEventArgs e)
    {
        Heater heater = (Heater)sender;
        HttpContext.Current.Response.Write("警告:现在温度是" + heater.temp.ToString() + "<br/>");
    }
}

若不使用委托,用观察者模式,改造如下:

public class HeaterSubject
{
    int temp=0;
    ArrayList observers;
    public HeaterSubject()
    {
        observers = new ArrayList();
    }

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

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

    public void BoilWater()
    {
        for (; temp <= 100; temp++)
        {
            if (temp >= 96)
            {
                Notice(temp);
            }
        }
    }

    void Notice(int temp)
    {
        foreach (Observer observer in observers)
        {
            observer.Update(temp);
        }
    }

}

public interface Observer
{
    void Update(int temp);
}

public class AlarmObserver : Observer
{
    public void Update(int temp)
    {
        HttpContext.Current.Response.Write("警告:现在温度是" + temp.ToString() + "<br/>");
    }
}

public class DisplayObserver : Observer
{
    public void Update(int temp)
    {
        HttpContext.Current.Response.Write("提示:水开了.温度是" + temp.ToString() + "<br/>");
    }
}

比较:

使用委托,则事件处理对象的方法名可以和委托不一致,但是签名需匹配.

使用观察者模式,事件处理对象需实现同一个接口.

何时使用委托?何时使用接口?

在以下情况中使用委托:

  • 当使用事件设计模式时。

  • 当封装静态方法可取时。

  • 当调用方不需要访问实现该方法的对象中的其他属性、方法或接口时。

  • 需要方便的组合。

  • 当类可能需要该方法的多个实现时。

在以下情况中使用接口:

  • 当存在一组可能被调用的相关方法时。

  • 当类只需要方法的单个实现时。

  • 当使用接口的类想要将该接口强制转换为其他接口或类类型时。

  • 当正在实现的方法链接到类的类型或标识时:例如比较方法

posted @ 2015-05-17 14:27  海绵宝  阅读(183)  评论(0编辑  收藏  举报