C#委托、事件和观察者模式

只谈情不闲聊 提交于 2020-03-03 07:06:15

委托的定义

委托是方法的载体,可以承载一个或多个方法,也可以将其看成一种特殊的数据类型,而这个数据类型存储的是方法,委托都派生于System.Delegate。委托是将方法当做变量使用,有利于解决代码冗余的问题和回调的问题。

委托的写法

如何写一个委托,首先是在类的前面书写,但是要点是需要知道当前这个委托是需要将什么方法当做变量存入到委托中去,方法有没有参数,如果有参数的话,那么书写时需要加入与方法一致的参数列表;其次要注意的是方法有没有返回值,若果有,那么这个委托也需要写入相同的返回值类型。简单实例如下:

//先简单写三个不同的方法
//第一个方法
public void Write(){//自定义内容,就不写了}
//第二个方法
public void Write(Student student)//这里的括号里面的Student是一个类
{
  //自定义内容;
}
//第三个方法
public string Write(string name)
{
 return name;
}
//如果要将第一个方法当做变量存入委托中,那么委托如下这么些
public delegate void WriteDelegate();
//同理第二个、第三个
public delegate void WriteDelegate(Student s);
public delegate string WriteDelegate(string s);

委托的使用

上面是在类的外面定义好了,然后就可以在类里面进行使用,简单的使用如下:

//Student类
class Student
{
   public WriteDelegate myDelegate;
   public void Write()
    {Console.WriteLine("这里用了委托");}
}
//主函数
public void Main()
{Student s=new Student();
//委托的简单实用
  s.myDelegate=new WriteDelegate(Write);//只需要讲方法名传进去就行了
 s.myDelegate();//也可以这样写:s.myDelegate.Invoke();
Console.ReadKey();
}

像上面的就是简单的使用,但是你会发现这样的使用会产生外界可以随意的控制我们的委托,要知道空委托是会导致错的,你会想在委托的使用上加一层限制,空委托就自动的报空,但是这并不是一个很好的方法,所以有了将委托封装起来,而且这样的封装也可以将委托里面传入更多的方法,也可以随时将方法移出委托。将上面的Student类更改一下,如下:

class Student
{
 private WriteDelegate myDelegate;
  public void Write()
  {Console.WriteLine("这里用了委托");}
//写个方法来注册委托,供外界使用
public void registeredDelegate(WriteDelegaet del)
{myDelegate+=del;}
//写个方法来注销委托,共外界调用
public void cancellationDelegate(WriteDelegaet del)
{myDelegate-=del;}
//写一个方法使用委托
public void useDelegate()
{myDelegate();}
}

这样在主函数中的使用方式就是这样的:

public void Main()
{
 Student s=new Student();
 s.registeredDelegate(s.Write);//加入了Write方法;
s.useDelegate();//使用了该委托;
s.cancellationDelegate(s.Write)//将Write方法从委托中移除
}

因为委托的本质是方法引用的队列,所以可以通过符号"+“和”-",来增删方法,一旦委托使用,就会将里面包含的方法全部调用完才会停止,如果委托重新赋值了,那么前面添加的方法会全部清空,例如s.myDelegate=null;这个操作,委托就清空了。
像上面第二种封装委托的方式,或者这种做法得到的就是一个事件。

事件的定义

如果像上面的第一种委托的用法,委托被公开出去了很不安全,所以我们通常是采用第二种方法,将委托封装起来,自己书写两个方法——注册委托和注销委托来供外界调用,委托调用方法在子方法里面,这样就会使委托很安全,这个就叫做事件。时间的特性:
外部不能随意的调用,这能注册和注销
只能自己去调用自己的委托
但是还有一种方法可以用来保护我问所定义的委托,就是用C#自带的event事件,如将上面的代码更改一下:

//Student中的更改
 public event WriteDelegate myDelegate;
//主函数中的更改
Student s=new Student();
s.myDelegate+=s.Write;
//s.myDelegate()//这个是没有办法用的
//用event修饰的委托变量会变成一个事件,外部可以调用这个变量,但是只能注册和注销,不能在外部进行触发,只能在内部触发

观察者模式

一系列对象监听另外一个对象的行为,被监听者一旦触发事件或者是消息,则所有的监听者收到,然后执行自己的行为。通俗的来说,就是使用委托/事件,让一系列的对象把他们的行为注册到我的委托中去,什么时候执行委托有自身决定,其他无法干涉。

 //老师类
    class Teacher
    {
        private string name;
        BellDelegate theBell;
        public Teacher(string name)
        {
            this.name = name;
        }
        public void ringingTheBell()
        {
            Console.WriteLine("{0}打铃了,下课!", name);
            commissionedByPrint();
        }
        public void registeredDel(BellDelegate del)
        {
            theBell += del;
        }
        public void cancellationDel(BellDelegate del)
        {
            theBell -= del;
        }
        private void commissionedByPrint()
        {
            theBell();
        }
    }
    //学生类
    class Student
    {
        private string name;
        private string things;
        public Student(string name,string things)
        {
            this.name = name;
            this.things = things;
        }
        public void activityToDo()
        {
            Console.WriteLine("{0}想要去{1}", name, things);
        }
    }
//主函数
public void Main()
{
            Teacher kolooas = new Teacher("Kolooas");
            Student xiaoming = new Student("小明", "买东西");
            Student xiaozhang = new Student("小张", "打水");
            Student xiaohong = new Student("小红", "做练习");
            Student xiaohua = new Student("小花", "打羽毛球");
            kolooas.registeredDel(xiaoming.activityToDo);
            kolooas.registeredDel(xiaozhang.activityToDo);
            kolooas.registeredDel(xiaohong.activityToDo);
            kolooas.registeredDel(xiaohua.activityToDo);
            kolooas.ringingTheBell();
       Console.ReadKey();
}

一旦老师打下课铃,学生的动作,这里的老师是被监听者,学生是监听者。

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!