委托与事件

.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/>");

    }

}

比较:

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

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

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

在以下情况中使用委托:

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

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

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

  • 需要方便的组合。

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

在以下情况中使用接口:

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

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

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

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

你可能感兴趣的:(事件)